一些简单的final知识不做说明,因为平时会用的,一下只说一下final的实现原理。

内存模型中的final(内存屏障实现)

在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。

先写入final变量,后调用该对象引用。【编译器会在final域的写之后,插入一个StoreStore屏障】

初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。

先读对象的引用,后读final变量。【编译器会在读final域操作的前面插入一个LoadLoad屏障

优点

  • final 关键字提高了性能,JVM 和 Java 应用都会缓存 final 变量
  • final 变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销

    补充

    final、finally、 finalize区别

  • final可以用来修饰类、方法、变量,分别有不同的意义,final修饰的class代表不可以继承扩展,final的变量是不可以修改的,而final的方法也是不可以重写的(override)。

  • finalize是基础类java.lang.Object的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize机制现在已经不推荐使用,并且在JDK 9开始被标记为deprecated。
  • finally则是Java保证重点代码一定要被执行的一种机制。我们可以使用try-finally或者try-catch-finally来进行类似关闭JDBC连接、保证unlock锁等动作。
    • 特例:下面的finally是不会进入的
      1. try {
      2. // do something
      3. System.exit(1);
      4. }
      5. finally {
      6. System.out.println("enter finally");
      7. }

      匿名内部类访问局部变量必须是final的?

      通俗的讲,就是为了保证外部类和内部类在同一个变量上的一致性问题。 内部类会持有外部类引用和方法中参数的引用,反编译class文件后,内部类的class文件的构造函数参数 中会显示传入 外部类对象(必然会加)以及方法内局部变量和形参(如果内部类有调用会加),不管是基本数据类型还是引用变量,如果重新赋值了,会导致内外指向的对象不一致,所以java就暴力的规定使用final,不能重新赋值。 至于jdk8的lambda表达式中引用,不需要再加fianl,只是一种语法糖。底层还是会自动加的。