为什么必须在构造函数完成之前初始化一个finalvariables?

为什么必须在构造函数完成之前初始化一个finalvariables?

public class Ex { final int q; } 

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

err:variablesq可能没有被初始化

官方原因是它是由Java语言规范8.3.1.2定义的:

一个空的final实例variables必须明确的分配在声明的类的每个构造函数的末尾 ; 否则会发生编译时错误。

一个空白的final是一个最终的variables,它的声明缺less一个初始化(即你所描述的)。

因为final不能修改variables,但是必须在某个时候初始化,而构造函数是正确的。

在你的情况下,这将被称为一个空白的最后,因为它没有声明时初始化。

finalvariables的值只能设置一次。 构造函数是类中代码的唯一位置,您可以保证这将保持真实; 构造函数只被调用过一次,但其他方法可以被调用多次。

finalvariables必须在声明或构造函数中初始化。

如果构造函数返回时尚未初始化,则可能永远不会初始化,并且可能仍然是未初始化的variables。 编译器不能certificate它会被初始化,从而引发错误。

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

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

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

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

final修饰符可以防止你改变variables的值,所以你必须在声明它的地方初始化它。

语言规范包含有关最终variables和字段属性的特定保证,其中一个是正确构造的对象(即构造器成功完成的对象)必须具有对所有线程初始化并可见的所有最终实例字段。 因此,编译器会分析代码path,并要求您初始化这些字段。

Final modifier不允许change your variable value 。所以你需要在某个地方给它赋值,在这种情况下, constructor就是你必须要做的地方。