为什么最终变量不总是一个常量表达式?

pai*_*dly 44 java expression constants compile-time-constant narrowing

在以下代码中:

final int a;
a=2;
byte b=a;   // error: possible loss of precision
Run Code Online (Sandbox Code Playgroud)

为什么我会收到此错误?是不是a最终变量编译时常量表达式,因此在赋值期间隐式缩小为字节?

换句话说,上面的代码不等同于:

final int a=2;
byte b=a;
Run Code Online (Sandbox Code Playgroud)

Sot*_*lis 51

来自JLS

一个空白的final是一个final变量,其声明中缺少一个初始化.

常量变量是使用常量表达式初始化final的基本类型或类型的变量 String(第15.28节).

你的变量

final int a;
Run Code Online (Sandbox Code Playgroud)

是一个空白final变量.它缺少初始化程序.第二段不适用于它,因为它未在声明时初始化.因此,它不是一个恒定的表达.

这也适用于领域.


Kev*_*man 42

编译器并不那么聪明.

我们可以说价值总是2.但是如果我们有这样的东西怎么办?

class ABC{
    final int a;

    public ABC(){
       if(Math.random() < .5){
          a = 2;
       }
       else{
          a = 12345;
       }

       byte b = a;
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器不够智能,无法区分这两种情况,因此它会给您一个错误.

  • 事实上,编译器不允许那么聪明. (30认同)
  • @LyingOnTheSky但即使计算是确定性的并且编译器可以解决它,它仍然不允许将其视为常量表达式(不需要转换).重要的是,有效的java程序是什么或不是什么不依赖于特定编译器的智能程度. (9认同)
  • @LyingOnTheSky很多.在C++中,编译器通常会添加自己的扩展.在Java中,它基本上是被禁止的(参见微软的诉讼). (3认同)