让我们看看下面的 Java 代码片段。
package trickyjava;
class A
{
public A(String s)
{
System.out.println(s);
}
}
final class B extends A
{
public B()
{
super(method()); // Calling the following method first.
}
private static String method()
{
return "method invoked";
}
}
final public class Main
{
public static void main(String[] args)
{
B b = new B();
}
}
按照约定,Java 中的super() 构造函数必须是相关构造函数主体中的第一条语句。在上面的代码中,我们调用了 super() 构造函数参数列表中的 static 方法 super(method());。
表示在构造函数B()中对super的调用中,正在调用一个方法 在调用 super 之前调用!这应该被编译器禁止,但它工作得很好。这在某种程度上等同于以下语句。
String s = method();
super(s);
但是,它是非法的,它会导致编译时错误,指示“对 super 的调用必须是构造函数中的第一条语句”。为什么?以及为什么它等效于 super(method()); 是有效的并且编译器不再提示?
最佳答案
这里的关键是 static
修饰符。静态方法绑定(bind)到类,实例方法(普通方法)绑定(bind)到对象(类实例)。构造函数从一个类初始化一个对象,因此该类必须已经完全加载。因此,作为构造函数的一部分调用静态方法是没有问题的。
加载类和创建对象的事件顺序是这样的:
- 加载类
- 初始化静态变量
- 创建对象
- 初始化对象<-- 使用构造函数
- 对象现在可以使用了
(简化*)
在调用对象构造函数时,静态方法和变量可用。
想想类及其 static
成员作为该类对象的蓝图。只有当蓝图已经存在时,您才能创建对象。
构造函数也称为初始化器。如果您从构造函数中抛出异常并打印堆栈跟踪,您会注意到它称为 <init>
在堆栈框架中。实例方法只能在对象构造完成后调用。无法使用实例方法作为 super(...)
的参数调用您的构造函数。
如果您创建同一个类的多个对象,则步骤 1 和 2 只会发生一次。
(*为清楚起见省略了静态初始化器和实例初始化器)
关于java - 在 super() 的参数列表中调用静态方法在 Java 中是有效的。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8100901/