final

final可修饰三类:变量、方法、类

变量

final修饰变量表示该变量是不可变的。例如 final int i =1; 在程序中i的值就不允许改变了。比较容易混淆的是final用来修饰引用变量时,表示该引用变量是不可变的即引用变量指向的内存地址是不变的,但是被指的内存地址中的类是可以改变的。例如:
final MyClass myClass = new MyClass();
这样声明myClass后,其所指向的内存地址就固定了,但仍然可以改变myClass所引用对象的成员变量。如果试图重用myClass这个变量,让其引用另一个对象则会出错。
myClass = new MyClass(); //``error!!!

方法

final修饰方法时表示该方法是不能被子类重写的。

final修饰类时表示该类是不能被继承的,由于java的单继承关系,所以该类是继承关系链中的终端。

pay attention !

  • final变量必须在声明的时候初始化或是在构造函数中初始化;
  • 接口中声明的所有变量都是final的;(interface中的变量是当作常量来设计的,它不但是final,而且还是public static的,也即interface中的变量一定是public static final的,换言之,这个变量实际上已经是个“常量”。)

    final和多线程

    final重排序规则

    1. public class FinalDemo {
    2. private int a; //普通域
    3. private final int b; //final域
    4. private static FinalDemo finalDemo;
    5. public FinalDemo() {
    6. a = 1; // 1. 写普通域
    7. b = 2; // 2. 写final域
    8. }
    9. public static void writer() {
    10. finalDemo = new FinalDemo();
    11. }
    12. public static void reader() {
    13. FinalDemo demo = finalDemo; // 3.读对象引用
    14. int a = demo.a; //4.读普通域
    15. int b = demo.b; //5.读final域
    16. }
    17. }

    假设线程A在执行writer()方法,线程B执行reader()方法。

写final域的重排序规则

  • JMM禁止编译器把final域的写重排序到构造函数之外;
  • 编译器会在final域写之后,构造函数return之前,插入一个storestore屏障。这个屏障可以禁止处理器把final域的写重排序到构造函数之外。

读final域重排序规则

  • 在读一个对象的final域之前,一定会先读包含这个final域的对象的引用。

省略………

final并发
JMM

finally

Java 中的 finally关键一般与try一起使用,在程序进入try块之后,无论程序是因为异常而中止或其它方式返回终止的,finally块的内容一定会被执行 。

finalize

Java中的对象并不一定会被全部垃圾回收,当你不想要该对象的时候,你需要手动去处理那些“特殊内存”。
Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize(),它用来清除回收对象。
不建议用finalize()方法完成“非内存资源”的清理工作,但建议用于:

  • 清理本地对象(通过JNI创建的对象);
  • 确保某些非内存资源(如Socket、文件等)的释放:在finalize()方法中显式调用其他资源释放方法。
    1. //关键字 protected 是一个限定符,它确保 finalize() 方法不会被该类以外的代码调用。
    2. protected void finalize()
    3. {
    4. // 在这里终结代码
    5. }