Loading

final详解

final详解

基础使用

修饰类

  • 表示该类不允许被继承.
  • 其所有方法隐式为final,无法覆盖.

注:
对于final类,可以通过组合方式对其扩展.

示例:

// 通过在类中构造一个私有的final类的实例,调用实例的方法,实现对应的功能.
// 再创建新的扩展方法
class newClass{
    private oldClass old;

    public void oldMethod(){
        old.oldMethod();
    }

    public void newMethod(){
        //...
    }
}

修饰方法

  • private方法为隐式的final
  • final方法可以被重载.
  • private final的方法不可被调用,子类通过向上转型无法调用父类的private final方法.

修饰参数

  • 无法在方法中修改参数执行的对象.

修饰变量

  • 不一定是编译期常量.
  • stataic final字段只能在声明或构造器中初始化.

示例:

Random r = new Random();
final int i = r.nextInt(); // 非编译期常量

final域重排序规则

写final域重排序规则

  • 在final域写之后,构造函数return之前,插入一个StoreStore屏障,禁止处理器把final域的写重排序到构造器之外.
  • 确保final对象在被线程可见之前已经被正确的初始化.

读final域重排序规则

  • 在读final域操作前插入LoadLoad屏障,禁止初次读对象和初次读对象包含的final域之间产生重排序.

final域为引用类型

final对象的成员域写操作

不能重排序一个final修饰的对象的成员域的写入和构造函数之外的对象的引用赋给一个引用变量.

public class Test{
    final int[] arrays;
    private Object obj;

    public Test(){
        arrays = new int[1];
        arrays[0] = 1;
    }

    public void method(){
        obj = new Object();
    }
}

小结:

  • 基本数据类型:
    • final域读:禁止final域写与构造方法重排序,保证所有线程可见,该对象的final域全部初始化.
    • final域写:禁止首次读对象的引用与读该对象包含的final域的重排序.
  • 引用数据类型:
    • 禁止在构造函数对一个final对象的成员域的写入与随后将该对象的引用赋值给引用变量重排序.

将指向对象的成员声明为final只能将该引用设为不可变,而非所指的对象.

final List l = new ArrayList();
l = new ArrayList(); // 不可以,引用不能指向新的对象
l.add("test"); // 可以,引用没有改变
posted @ 2020-06-30 21:34  战五渣渣渣渣渣  阅读(271)  评论(0编辑  收藏  举报