Java 编译时常数
我理解了编译时常量规则的由来Java 编译时常数,java,compiler-errors,compilation,constants,compile-time-constant,Java,Compiler Errors,Compilation,Constants,Compile Time Constant,我理解了编译时常量规则的由来 宣布为最终决定 具有基元或字符串类型 与声明同时初始化 用常量表达式初始化 但我无法理解为什么下面的代码不能: final int x; x = 5; 唯一的区别是上面第三点。 不同行而不是同一行上的初始化如何产生差异。案例1最终int x=5 public static void main(String[] args) { final int x = 5; } public static void main(String[] args) {
但我无法理解为什么下面的代码不能:
final int x;
x = 5;
唯一的区别是上面第三点。
不同行而不是同一行上的初始化如何产生差异。案例1
最终int x=5代码>
public static void main(String[] args) {
final int x = 5;
}
public static void main(String[] args) {
final int x;
x = 5;
}
生成的字节码是:
public static main([Ljava/lang/String;)V
L0
LINENUMBER 3 L0
ICONST_5
ISTORE 1
L1
LINENUMBER 4 L1
RETURN
L2
LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
LOCALVARIABLE x I L1 L2 1
MAXSTACK = 1
MAXLOCALS = 2
public static main([Ljava/lang/String;)V
L0
LINENUMBER 4 L0
ICONST_5
ISTORE 1
L1
LINENUMBER 5 L1
RETURN
L2
LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
LOCALVARIABLE x I L1 L2 1
MAXSTACK = 1
MAXLOCALS = 2
案例2最终整数x;x=5代码>
public static void main(String[] args) {
final int x = 5;
}
public static void main(String[] args) {
final int x;
x = 5;
}
生成的字节码是:
public static main([Ljava/lang/String;)V
L0
LINENUMBER 3 L0
ICONST_5
ISTORE 1
L1
LINENUMBER 4 L1
RETURN
L2
LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
LOCALVARIABLE x I L1 L2 1
MAXSTACK = 1
MAXLOCALS = 2
public static main([Ljava/lang/String;)V
L0
LINENUMBER 4 L0
ICONST_5
ISTORE 1
L1
LINENUMBER 5 L1
RETURN
L2
LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
LOCALVARIABLE x I L1 L2 1
MAXSTACK = 1
MAXLOCALS = 2
正如您所看到的,除了行号,这两种情况之间没有区别
事实上,在InteliJ这样的ide中,您将看到将案例2的两行连接到案例1的一行的提示(作为灯泡)。
如果您阅读了所提供链接中的所有答案和评论,
关于这一点,你会感到困惑而不是明智
这都是关于术语的,在本例中,没有记录在案术语
这是该链接中答案之一的摘录:
JLS不包含短语编译时常量
然而,程序员经常使用编译时常量和常量这两个术语
可互换地
现在来看编译器如何使用这两种情况
如果在两种方法的末尾添加此行:
System.out.println(x);
生成的字节码是:
对于情况1
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ICONST_5
INVOKEVIRTUAL java/io/PrintStream.println (I)V
对于情况2
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ILOAD 1
INVOKEVIRTUAL java/io/PrintStream.println (I)V
第二种情况有所不同:ILOAD 1
而不是ICONST_5
在第一种情况下,x
的含义被5替换,而在第二种情况下则不是,并且调用(加载)了x
的值以执行语句。来自:
常量变量是使用常量表达式(§15.28)初始化的基元类型或字符串类型的最终变量
如果变量是在未初始化的情况下声明的,则根据定义它不是常量变量,即使最终指定给它的值是常量表达式。当这两行被试图访问x
的其他语句分隔时,可能会出现编译时错误。否则我不确定什么对你不起作用!我认为他们也针对一套不太复杂的规则。我无法想象一个可管理的规则能够覆盖你的第二个片段而不给其他地方带来麻烦。限制在哪里?我投票结束这个问题,因为答案只能是猜测(最好是思想阅读),运行代码final int a=1;最终int b;b=2;开关(1){case a://OK case b://compile error如果任何变量被声明为final,这意味着它只能初始化一次,这应该在声明@NizamMuch时发生更好的解释,但我观察到的是,在后端运行时可能会有轻微的差异,但在前端,它们的行为将是相同的,即在co上解决方案他们都将打印5,并且永远不能重新分配@forpas@Nizam当然永远不能重新分配,因为它们被声明为final
。区别(从字节码可以看出)在于,在第一种情况下,x
的值在编译时替换对x
的每个引用。