一些简单的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是不会进入的
try {
// do something
System.exit(1);
}
finally {
System.out.println("enter finally");
}
匿名内部类访问局部变量必须是final的?
通俗的讲,就是为了保证外部类和内部类在同一个变量上的一致性问题。 内部类会持有外部类引用和方法中参数的引用,反编译class文件后,内部类的class文件的构造函数参数 中会显示传入 外部类对象(必然会加)以及方法内局部变量和形参(如果内部类有调用会加),不管是基本数据类型还是引用变量,如果重新赋值了,会导致内外指向的对象不一致,所以java就暴力的规定使用final,不能重新赋值。 至于jdk8的lambda表达式中引用,不需要再加fianl,只是一种语法糖。底层还是会自动加的。
- 特例:下面的finally是不会进入的