final变量和编译时常量之间有什么区别?
考虑以下代码:
final int a = 5;
final int b;
b=6;
int x=0;
switch(x)
{
case a: //no error
case b: //compiler error
}
这是什么意思?何时和如何为最终变量分配值?运行时会发生什么?编译时会发生什么?为什么我们应该为 switch 提供一个编译时常量?Java 的哪些其他结构需要编译时常量?
final变量和编译时常量之间有什么区别?
考虑以下代码:
final int a = 5;
final int b;
b=6;
int x=0;
switch(x)
{
case a: //no error
case b: //compiler error
}
这是什么意思?何时和如何为最终变量分配值?运行时会发生什么?编译时会发生什么?为什么我们应该为 switch 提供一个编译时常量?Java 的哪些其他结构需要编译时常量?
问题在于,所有的case:
语句必须在编译时达到最终状态。你的第一个语句已经到达最终状态。a
将百分之百地没有除5
以外的其他值。
final int a = 5;
然而,对于b
并不保证如此。如果在b
周围有一个if语句会怎么样呢?
final int b;
if(something())
b=6;
else
b=5;
这是什么意思?
这意味着“b”不是编译时常量表达式,而JLS要求它是。
什么时候和如何为final变量赋值?
正式地说,当执行赋值语句或初始化器时。
但实际上,如果final
声明为编译时常量,则表达式在编译时计算,并且其值被硬编码到代码中。
在运行时会发生什么,在编译时会发生什么?
见上文。
为什么我们应该给switch一个编译时常量?
因为JLS要求这样做。
这对于字节码编译器来检查switch语句是否格式良好是必要的;即switch常量的值不冲突。它还允许JIT编译器生成针对switch常量实际值进行优化的代码。
Java的哪些其他结构需要编译时常量?
我想不出有其他的,就这些。
从编译器角度看,您试图使用一个可能没有初始化的变量b。switch语句被编译成JVM字节码表格或查找表,需要在case语句中使用的值是编译时常量而且唯一的。
final int a = 4; // compiler is sure a is initialized
final int b;// variable b is not guranted to be assigned
例如:尽管这个语句最终会初始化变量b,但编译器无法检测到它。
if (a < 4) b= 10;
if (a >= 4) b = 8
switch语句需要一个常量。由于final变量可以延迟初始化,编译器无法确定在case分支中b是否有值。
final int b;
只能被赋值一次,其值在运行时根据条件而定,这就是为什么即使是一个final变量,它也不是编译时常量,尽管它将是一个运行时常量,而案例需要编译时常量。