为什么必须在构造函数完成之前初始化最终变量?

sar*_*nan 40 java

为什么必须在构造函数完成之前初始化最终变量?

public class Ex
{
  final int q;
}
Run Code Online (Sandbox Code Playgroud)

当我编译这段代码时,我得到这样的错误

错误:变量q可能尚未初始化

ass*_*ias 35

官方理由是,它是由定义的Java语言规范8.3.1.2:

必须在声明它的类的每个构造函数的末尾明确赋值空白的最终实例变量 ; 否则会发生编译时错误.

空白最终是一个最终变量,其声明缺少初始化程序(即您描述的内容).

  • 这个答案只重述了OP提到的行为.它没有说明行为的原因,这是OP提出的问题. (4认同)

jop*_*rat 15

因为final阻止您修改变量,但必须在某个时刻进行初始化,并且构造函数是正确的位置.

在您的情况下,它将被称为空白最终,因为它在声明时未初始化.


Dav*_*ebb 14

final变量的值只能设置一次.构造函数是类的代码中唯一可以保证它将成立的地方; 构造函数只为一个对象调用一次,但其他方法可以被调用任意次.


Ken*_*rey 10

一个final变量必须在声明或构造函数初始化.

如果在构造函数返回时尚未初始化它,则它可能永远不会被初始化,并且可能仍然是未初始化的变量.编译器无法证明它将被初始化,因此会抛出错误.

这个维基百科摘录解释得很好:

最终变量只能通过初始化程序或赋值语句初始化一次.它不需要在声明点初始化:这称为"空白最终"变量.必须在声明它的类的每个构造函数的末尾明确赋值类的空白最终实例变量; 类似地,必须在声明它的类的静态初始值设定项中明确赋值空白的最终静态变量:否则,在两种情况下都会发生编译时错误.(注意:如果变量是引用,这意味着变量不能重新绑定到引用另一个对象.但它引用的对象仍然是可变的,如果它最初是可变的.)


Miq*_*uel 6

final应用于字段的关键字具有以下两种效果之一:

  • 在原语上,它可以防止原语的值被更改(int不能更改值)
  • 在一个对象上,它可以防止"变量的值",即对象的引用被更改.也就是说,如果你有一个final HashMap<String,String> a,你将只能设置一次,你将无法再做this.a=new HashMap<String,String>();一次,但是没有什么能阻止你做this.a.put("a","b"),因为那不会修改引用,只有对象的内容.


Ada*_*nos 2

修饰符final阻止您更改变量值,因此您必须在声明它的地方对其进行初始化。