我了解Compile-time constants and variables中的编译时间常数规则。
final int x = 5;
但是我不明白为什么下面的代码没有:
final int x;
x = 5;
唯一的区别是上面的第三点。 在不同的行而不是同一行上进行初始化有何不同?
答案 0 :(得分:0)
案例1 final int x = 5;
public static void main(String[] args) {
final int 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
案例2 final int x; x = 5;
public static void main(String[] args) {
final int x;
x = 5;
}
生成的字节码为:
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的想法中,您会看到提示(作为灯泡)将案例2的2行连接到案例1的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
的值被调用(加载)以执行该语句。
答案 1 :(得分:0)
常量变量是原始类型或字符串类型的最终变量,使用常量表达式(第15.28节)初始化。
如果声明变量时未进行初始化,则根据定义,它不是常数变量,即使最终分配给它的值是常数表达式。