【问题标题】:Only super class is initialized even though static field is referenced using sub type即使使用子类型引用静态字段,也仅初始化超类
【发布时间】:2023-04-09 23:18:01
【问题描述】:

我正在做一些关于 JAVA 初始化过程的研究。 这是一个很好的参考材料: When a class is loaded and initialized in JVM

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

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

我的解释有什么问题?


编辑

  1. 它会触发超类静态初始化。
  2. 如果静态字段是final,并且静态final字段在声明时被初始化。然后它既不会加载类也不会初始化类,因为这个静态最终字段是一个编译时常量值。 注意:如果 static final 字段在静态块中初始化,则此语句不再成立。

【问题讨论】:

  • 当您访问一个静态字段时,与之关联的类会被初始化。 JVM 不会寻找其他哪些类引用这个类并实例化。

标签: java static initialization


【解决方案1】:

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

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;

并且会打印“Initializing Superclass”,即使源代码引用了Subclass

【讨论】:

  • 你怎么知道这个例子。我花了几个小时来考虑它。并且失败了。该块还说“它不会触发超类的初始化或”你能再举一个例子吗?
  • @Zack:这意味着如果 Superclass 在这种情况下有一个非 Object 超类,那么 that 也不会被初始化。编辑:除了我已经检查过,它 is 已初始化,这是我所期望的。我认为文章的那部分是错误的。
  • 是的,我已经尝试过了。它真正初始化了定义静态字段的类的超类。
  • @Zack:确实,我阅读规范的方式是意料之中的。我认为文章的位是错误的,尽管我的回答中提到的那位是正确的。
【解决方案2】:

一个例子:

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。

【讨论】:

    【解决方案3】:

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

    但是这里据说只会打印“Initializing Superclass”。 有人可以澄清一下吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 2010-12-02
      相关资源
      最近更新 更多