java-doc-final

final

变量声明为final,可以防止修改变量的内容,本质上就是将变量变成了常量。这意味着final变量必须在声明时进行初始化。可以通过两种方式完成这个工作:

  • 可以在声明时为其提供一个值
  • 可以在构造函数中为其赋值

final变量名全部使用大写,这是一种常见的编码阅读。
除了可以将变量声明为final之外,方法参数和局部变量也可以声明为final。将参数声明为final,可以防止在方法中修改参数。将局部变量声明为final,可以防止多次为其赋值。
关键字final也可以应用于方法,但是含义于应用于变量有本质区别。

1
2
3
4
5
6
7
8
9
10
class Test
{
final int FIANL_VAL1 = 1;
final int FINAL_VAL2;

Test()
{
this.FINAL_VAL2 = 2;
}
}

final在JMM中的处理

  • final在该对象的构造函数中设置对象的字段,当线程看到该对象时,将始终看到该对象的final字段的正确构造版
    本。
    伪代码示例: f = new finalDemo(); 读取到的 f.x 一定最新, x为final字段

  • 如果在构造函数中设置字段后发生读取,则会看到该final字段分配的值,否则它将看到默认值;
    伪代码示例: public finalDemo(){ x = 1; y = x; }; y会等于1;

  • 读取该共享对象的final成员变量之前,先要读取共享对象。
    伪代码示例: r = new ReferenceObj(); k = r.f ; 这两个操作不能重排序

  • 通常被static final修饰的字段, 不能被修改 。然而System.in、 System.out、 System.err被static final修饰,却可以修改,遗留问题, 必须允许通过set方法改变,我们将这些字段称为写保护,以区别于普通final字段;

多线程编程

  • 希望变量在构造的时候被其他线程正常读取