final
final可修饰三类:变量、方法、类
变量
final
修饰变量表示该变量是不可变的。例如 final int i =1;
在程序中i的值就不允许改变了。比较容易混淆的是final用来修饰引用变量时,表示该引用变量是不可变的即引用变量指向的内存地址是不变的,但是被指的内存地址中的类是可以改变的。例如:final MyClass myClass = new MyClass();
这样声明myClass后,其所指向的内存地址就固定了,但仍然可以改变myClass所引用对象的成员变量。如果试图重用myClass这个变量,让其引用另一个对象则会出错。myClass = new MyClass(); //``error!!!
方法
类
final
修饰类时表示该类是不能被继承的,由于java的单继承关系,所以该类是继承关系链中的终端。
pay attention !
final
变量必须在声明的时候初始化或是在构造函数中初始化;接口中声明的所有变量都是
final
的;(interface中的变量是当作常量来设计的,它不但是final,而且还是public static的,也即interface中的变量一定是public static final的,换言之,这个变量实际上已经是个“常量”。)final和多线程
final重排序规则
public class FinalDemo {
private int a; //普通域
private final int b; //final域
private static FinalDemo finalDemo;
public FinalDemo() {
a = 1; // 1. 写普通域
b = 2; // 2. 写final域
}
public static void writer() {
finalDemo = new FinalDemo();
}
public static void reader() {
FinalDemo demo = finalDemo; // 3.读对象引用
int a = demo.a; //4.读普通域
int b = demo.b; //5.读final域
}
}
假设线程A在执行writer()方法,线程B执行reader()方法。
写final域的重排序规则
- JMM禁止编译器把final域的写重排序到构造函数之外;
- 编译器会在final域写之后,构造函数return之前,插入一个storestore屏障。这个屏障可以禁止处理器把final域的写重排序到构造函数之外。
读final域重排序规则
- 在读一个对象的final域之前,一定会先读包含这个final域的对象的引用。
省略………
finally
Java 中的 finally
关键一般与try一起使用,在程序进入try块之后,无论程序是因为异常而中止或其它方式返回终止的,finally块的内容一定会被执行 。
finalize
Java中的对象并不一定会被全部垃圾回收,当你不想要该对象的时候,你需要手动去处理那些“特殊内存”。
Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize()
,它用来清除回收对象。
不建议用finalize()
方法完成“非内存资源”的清理工作,但建议用于:
- 清理本地对象(通过JNI创建的对象);
- 确保某些非内存资源(如Socket、文件等)的释放:在
finalize()
方法中显式调用其他资源释放方法。//关键字 protected 是一个限定符,它确保 finalize() 方法不会被该类以外的代码调用。
protected void finalize()
{
// 在这里终结代码
}