java - 在 super() 的参数列表中调用静态方法在 Java 中是有效的。为什么?

标签 java static

让我们看看下面的 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)到对象(类实例)。构造函数从一个类初始化一个对象,因此该类必须已经完全加载。因此,作为构造函数的一部分调用静态方法是没有问题的。

加载类和创建对象的事件顺序是这样的:

  1. 加载类
  2. 初始化静态变量
  3. 创建对象
  4. 初始化对象<-- 使用构造函数
  5. 对象现在可以使用了

(简化*)

在调用对象构造函数时,静态方法和变量可用。

想想类及其 static成员作为该类对象的蓝图。只有当蓝图已经存在时,您才能创建对象。

构造函数也称为初始化器。如果您从构造函数中抛出异常并打印堆栈跟踪,您会注意到它称为 <init>在堆栈框架中。实例方法只能在对象构造完成后调用。无法使用实例方法作为 super(...) 的参数调用您的构造函数。

如果您创建同一个类的多个对象,则步骤 1 和 2 只会发生一次。

(*为清楚起见省略了静态初始化器和实例初始化器)

关于java - 在 super() 的参数列表中调用静态方法在 Java 中是有效的。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8100901/

相关文章:

java - 如何捕获URL中的特定文本?

powershell - 为什么 `[SomeType] | Get-Member -Static`返回 `SomeType`的静态成员而不是 `System.RuntimeType`的静态成员?

c - 需要动态分配(初始化)的静态变量

C++ "fatal error LNK1120"未解析的静态类成员

java - 数据库设计 - 使用 Short 而不是 Varchar - 用于状态字段

java - 如何在openwrt系统上部署java嵌入式套装

java - 为什么我的程序没有删除 "all"?

c++ - 有没有办法在不破坏封装的情况下为模板类(所有类型)使用一个静态变量

php - PHP中的静态方法与非静态方法有什么区别吗?

java - 如何通过流为 C++、Java 和 Python 交换二进制结构化数据?