【问题标题】:Static block is not being called未调用静态块
【发布时间】:2013-09-24 10:32:03
【问题描述】:

谁能解释这是怎么回事?

public class MagicFinal {

    public static void main(String[] args) {
        System.out.println(A.s);
    }
}

class A {
    static {
        System.out.println("class has been loaded");
    }

    public static final String s = "final";

    public static final Integer i = 3;
    
        
}

控制台:

最终

这是什么?我不明白为什么没有加载类,我知道类总是在第一次调用时加载。字段s 在字符串池中,我看到 final 修饰符很神奇。

如果我删除 final 修饰符 (public static String s = "final") 我会得到

控制台:

类已加载

最终

注意:我已更改字段 i : public static final int i = 3; 并在控制台中显示它。 我得到了与字符串情况相同的情况。为什么?

【问题讨论】:

    标签: java final


    【解决方案1】:

    "final" 是一个字符串文字,因此是一个compile-time constant expression。使用编译时常量表达式初始化的static final 变量的值直接硬编码到引用它的类中,并且不引用原始类。因此,原始类的初始化不会发生。

    另外,请注意类加载和类初始化之间的区别:只有后者的出现是由JLS精确指定的。类加载可以随时发生。

    【讨论】:

    • 好的,非常感谢!!整数呢??公共静态最终 int i = 3; // 不会写类已经加载 public static final Integer i = 3; // 写入类已加载
    • 请阅读我在回答中链接到的编译时常量表达式的定义。 int 是原始值,String 是唯一可以包含在常量表达式中的引用类型值的特殊情况,Integer 两者都不是。
    • @marko - 你是在告诉我 A 类根本没有加载吗?还是延迟初始化的情况???
    • @X86 如果"class has been loaded" 没有打印出来,那么这个类还没有被初始化。根据 JLS,类总是延迟初始化。 A 类可能在任何时候加载,也可能根本不加载,这取决于 JVM 运行时的决定。请注意,类加载不应导致任何可观察到的效果。
    • @x86 我不关注你。如果 A 类中的字段为 static final,则根本不会初始化 A 类。它可能会或可能不会被加载,但这与这个故事无关。它很可能不会被加载,但没有什么能阻止 JVM 这样做。
    【解决方案2】:

    这是 Java 语言规范 {8.3.2.1 类变量的初始化程序} 中所写的内容。这必须回答你的问题

    这里的一个微妙之处是,在运行时,静态变量是最终的,并且 用编译时常量值初始化,首先初始化。这也是 适用于接口中的此类字段(第 9.3.1 节)。这些变量是“常数” 永远不会被观察到具有默认初始值(§4.12.5),即使是狡猾的 程式。更多讨论请参见 §12.4.2 和 §13.4.9。

    【讨论】:

    • 您似乎指的是Java 语言规范,第三版The Java® Language Specification Java SE 7 Edition中没有这样的段落。
    • 是的。没错。我正在研究旧版本,但该声明也适用于 JLS 7。下面的行来自 JLS7 在运行时,最终的静态字段和使用常量表达式(第 15.28 节)初始化的静态字段首先被初始化(第 12.4.2 节)。这也适用于接口中的此类字段(第 9.3.1 节)。这些字段是“常量”,永远不会被观察到具有默认初始值(§4.12.5),即使是不正当的程序(§13.4.9)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-17
    • 1970-01-01
    相关资源
    最近更新 更多