请问 Java 中的“编译期可知,运行期不变”的父类方法是什么?

2020-09-22 20:21:53 +08:00
 Newyorkcity

方法在程序真正运行之前就有一个可确定的调用版本,并且这个方法的调用版本在运行期是不可改变的。换句话说,调用目标在程序代码写好、编译器进行编译那一刻就已经确定下来。这类方法的调用被称为解析( Resolution )。

只要能被 invokestatic 和 invokespecial 指令调用的方法,都可以在解析阶段中确定唯一的调用版本,Java 语言里符合这个条件的方法共有静态方法、私有方法、实例构造器、父类方法 4 种,再加上被 final 修饰的方法(尽管它使用 invokevirtual 指令调用),这 5 种方法调用会在类加载的时候就可以把符号引用解析为该方法的直接引用。这些方法统称为“非虚方法”( Non-Virtual Method ),与之相反,其他方法就被称为“虚方法”( Virtual Method )。

以上内容出自周志明先生的《深入 JVM (第三版)》,结合两段内容可以推论『父类方法是在程序代码写好、编译器进行编译那一刻就已经确定下来的』,我本来是从字面上理解就是父类中的方法,但父类中的方法应该不具备这么腰椎盘突出的性质吧。。。

谢谢

1069 次点击
所在节点    问与答
4 条回复
codehz
2020-09-22 20:53:19 +08:00
所有能写出来的方法都是编译期可知,运行期不变啊,除非你用 asm 库动态创建,但是创建的过程逻辑上也是编译期(
你在不绕过 jvm 的情况下能写出运行期可变的 java 方法吗(
Newyorkcity
2020-09-23 00:07:44 +08:00
@codehz

```java
import java.util.Random;

public class Main {
public static void main(String[] args) {
final Random random = new Random();
Human person = random.nextBoolean() ? new Man() : new Woman();
person.say();
}

static abstract class Human {
abstract void say();
}

static class Man extends Human {
@Override
void say() {
System.out.println("I am male.");
}
}

static class Woman extends Human {
@Override
void say() {
System.out.println("I am female");
}
}
}
```
codehz
2020-09-23 00:40:07 +08:00
@Newyorkcity 哦,我理解错了,看题目我以为是类的问题
geelaw
2020-09-23 00:54:11 +08:00
父类方法是指用 super 调用的基类中方法(的版本)。

例如
class B { public void Foo() { } }
class D extends B { @Override public void Foo() { super.Foo(); } }
这里面 super.Foo 调用 B.Foo 是编译时决定的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/709539

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX