为什么静态块中的代码不会执行?

9
当我在main中打印constant时,static块不会执行,但是当我打印stat时它会执行。在Java中,static final有什么重要性吗?
package com.test.doubt;

class Doubt {

  public static final int constant = 123;
  public static int stat = 123;

  static {
    System.out.println("Static Block");
  }
}

public class MyProgram {

  public static void main(String[] args) {
    System.out.println(Doubt.constant);
  }
}
2个回答

21

你的代码没有初始化 Doubt 类,这是因为 Doubt.constant 是一个常量。它的值在编译时被嵌入到 MyProgram 中 - 甚至在编译后删除 Doubt.class ,你的程序仍然可以运行。

运行

javap -c com.test.doubt.MyProgram

查看编译后的代码确切样子,可以执行以下操作。

请参阅JLS第15.28节,了解常量表达式的构成方式。例如,以下内容仍然是一个常量表达式:

public static final String FOO = "Foo";

所有这些都会这样做:全部

public static final String FOO = "Foo";
public static final String BAR = "Bar";
public static final String FOOBAR = FOO + BAR;

... 但这样做并不可行。

public static final String NOT_A_CONSTANT = "Foo".substring(0, 1);

1
换句话说,javac编译器优化掉了Doubt类的需要。 - Peter Lawrey
3
不,对于String类型来说也会发生这种情况,只要它是编译时常量。有关详细信息,请参阅JLS的第15.28节。 - Jon Skeet
1
还要注意这种情况的副作用,即当您尝试通过更新所引用的类文件来更改常量时,它是不起作用的。因为该定义仅在编译时(使用它的类的编译时)使用。 - Thilo
@jenuine您正在使用编译时不是常量的值,因此必须加载该类。 - Peter Lawrey
回复:字符串。哇,我不知道那个。那是针对字符串的特殊处理吗?它不能适用于任何旧对象,对吧? - Thilo
显示剩余6条评论

11

static final int会直接编译成其值的代码插入到你的代码中。也就是说,JVM看到并执行的是:

System.out.println(123);

而且您根本没有碰您恰当命名的 Doubt 类(顺便说一下,这是不建议以此方式指定常量的一个理由。如果您更改该值,则必须重新编译每个引用类)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接