【问题标题】:Why is the static initializer not executed if referenced static field is final [duplicate]如果引用的静态字段是最终的,为什么不执行静态初始化程序[重复]
【发布时间】:2014-06-17 17:51:05
【问题描述】:
class a
{
    static final  int a =5;
    static {
        System.out.println("hi");

    }
}
class b
{
    public static void main(String[] args) {
        System.out.println(a.a);
    }   

}

为什么静态块不运行,输出只有

5

而如果我从类变量中删除 final 关键字,静态块将被执行并且输出变为

hi 
5

【问题讨论】:

  • 一旦将值分配给具有final 修饰符的原始数据类型,您就无法再次更改该值,换句话说,您无法重新分配变量a 以获得新的值不是 int 5。如果你尝试这样做,你会得到一个编译器错误。
  • 这实际上是一个很好的问题,它的标题有点误导,导致投反对票。
  • @geoand 那么我应该对标题进行哪些编辑?
  • @user3239652 一个建议是“静态和最终修饰符的组合结果是否对静态块执行有任何影响”。沿着这些思路,因为你现在的标题向一些人暗示你实际上并不知道 final 是做什么的。
  • @user3239652 更新了我的答案,包括触发静态块的几种方式

标签: java static final


【解决方案1】:

因为带有关键字static final 的变量是编译时常量,不会触发包含该字段的类的加载。

尝试在变量 a

上使用 static final 运行此代码
System.out.println(a.a)
a var = new a();

如您所见,输出将是

5
hi

调用 a 时不会触发静态块,但在创建类的实例时会触发它。它可以由以下任何一种触发:

  • 创建了一个类的实例,
  • 调用了类的静态方法,
  • 分配了类的静态字段,
  • 使用了非常量静态字段,或者
  • 对于顶级类,执行词法嵌套在类中的断言语句。

一个与您的问题非常相似的问题可能会有所帮助: Static block in Java not executed

【讨论】:

  • 我认为这并不完全正确。 statics 应该在加载类时初始化,并且应该由引用它的 b 加载。然而,正如@endriu_l 在他的回答中解释的那样,编译器在b 中内联字段a.a 的值,因此永远不会加载类a,这意味着永远不会执行static
【解决方案2】:

基本上发生的事情是原语和字符串上的static final组合导致编译器内联它们,这可能阻止了静态初始化块的执行,因为类加载器永远不会加载a类,因为a.a 在编译期间已解决

【讨论】:

  • 好地方,如果你用javap列出字节码,你可以看到变量是内联的
猜你喜欢
  • 2014-10-06
  • 2019-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 2017-12-07
  • 2015-05-24
相关资源
最近更新 更多