当前位置: 首页 > 知识库问答 >
问题:

即使使用子类型引用静态字段,也只初始化超类

韩照
2023-03-14

我正在做一些关于JAVA初始化过程的研究。这里有一个很好的参考材料:当一个类在JVM中加载和初始化时

在这个页面上有规则说: 3)如果类初始化是由于访问静态字段而触发的,只有声明静态字段的类被初始化,即使静态字段被类型的子引用,它也不会触发超级类或子类的初始化类,子接口或接口的实现类。

我真的不明白这个想法。如果静态字段被Subclass引用,那么这个字段当然需要创建一个子类对象或由Subclass对象分配。因此,它肯定会触发子类初始化。

我的解释有什么问题?

编辑:

  1. 它确实触发了Super Class静态初始化。
  2. 如果静态字段是最终字段,并且静态最终字段在声明时被初始化。然后它既不加载类,也不初始化类,因为这个静态最终字段是编译时常量值。注意:如果静态最终字段在静态块中初始化,则此语句不再有效。

共有3个答案

郑宜民
2023-03-14

如上所示,当我运行超类/子类示例时,调用子类。INIT_TIME,超类和子类静态初始化器都被调用。

但在这里,据说只会打印“初始化超类”。有人能澄清一下吗?

凤高翰
2023-03-14

例如:

class A {
   public static int nA = 0;
}

class B extends A {
   public static int nB = 1;
}

class C extends B {
   public static int nC = 2;
}

客户:

int test = B.nA;

JVM将只初始化类A,而不是B或C。

向和歌
2023-03-14

我认为关键是在这种情况下:

public class Superclass {
    public static long INIT_TIME = System.currentTimeMillis();

    static {
        System.out.println("Initializing Superclass");
    }
}

public class Subclass extends Superclass {
    static {
        System.out.println("Initializing Subclass");
    }
}

此代码:

long time = Subclass.INIT_TIME;

实际编译为:

long time = Superclass.INIT_TIME;

即使源代码引用了子类,也只会打印“初始化超类”。

 类似资料:
  • 问题内容: SuperClass object = new SubClass(); 为什么使用超类实例化上面的子类对象?因为我学会实例化对象的唯一方法是: 我正在学习Java。 问题答案: 您可能有一个仅接受实例的方法。由于 是 ,您可以使用的实例并将其视为。 使用接口时,会使用相同的行为: 这就是多态的美。它允许您更改类内部的实现,而无需破坏其余代码。

  • 当一个类本身有一个静态实例时,我很难理解初始化顺序。另外,为什么

  • 静态字段何时初始化?如果我从未实例化过一个类,但我访问了一个静态字段,那么用于实例化私有静态字段的所有静态块和私有静态方法(按顺序)都在那一刻被调用了吗?或者什么时候启动应用程序?

  • 我想将一些对象实例绑定到使用Javassist创建的类。该对象是从某个源读取的,数据是预先未知的。 但当我检查API时,Javassist似乎创建了一个真正的字节码,它以“调用这个”或“实例化那个”或“使用这个常量”的形式存储初始化。 有没有办法让Javassist向运行时给定的现有实例添加一个初始化的静态字段?

  • 我正在设计一款纯文字的电子游戏,游戏中的两个角色不常出现在一起,但在内心和性格上非常相似。 我的问题是,我不知道如何通过使用静态最终内部常量的构造函数初始化常量。否则这场比赛就可以开始了 这是一个两难的问题: 如果我没弄错的话,枚举常量必须在枚举的第一行定义 我如何解决这个第22条军规? 以下是根据保密协议从游戏中发布的一些示例代码: 我试图用马里奥的“典型”来初始化SUPERMARIO,但我还没

  • 我找不到任何关于这个具体案例的具体SO帖子,所以我想问一下我认为是/否的问题。 以下是JLS§12.4.2(Java SE 8),清单6-7: 我的问题是:这是否意味着子类的final static变量在超类的静态初始化之前初始化(假设final static作为其声明的一部分初始化)?