1. final、finalize、finally 的区别
① final 修饰词
- final修饰类:最终类,不能被继承,如String、Math、System均为final修饰的类
- final修饰方法:最终方法,不能被覆盖
- final修饰变量:基本类型变量,值不可变;引用类型变量,地址不可变
- final作为形参使用的好处:拷贝引用,为了避免引用的地址值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。
② finalize() 方法
当对象被判定为辣鸡对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列。
- 自动回收机制:JVM的内存耗尽,一次性回收所有辣鸡对象。
- 手动回收机制:使用 System.gc() 通知JVM触发垃圾回收。
③ finally 关键字
finally 关键字:
作为异常处理的一部分,它只能用在try-catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常/不管是否有return),经常被用在需要释放资源的情况下。
2. finally 特点探讨
2.1 finally 常用于释放资源
finally触发资源回收代码演示: - 可参考finalize()方法的描述
public class TestFinally {
public static void main(String[] args) {
TestClass t = new TestClass ();
try {
t = null;
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
System.gc();
}
System.out.println(t); // null
}
}
class TestClass {
@Override
protected void finalize() throws Throwable {
super.finalize(); // 千万不要改
System.out.println("进入JVM垃圾回收队列");
}
}
Java测试finally
2.2 finally 与 return 探讨 (3个例子对比)
finally与return测试例子1:
public class TestFinally1 {
public static void main(String[] args) {
System.out.println( method(11) );
}
public static int method(int n) {
try {
if (n % 2 == 0) {
throw new RuntimeException();
} else {
System.out.println("奇数");
}
return 1; // 执行了return
} catch (Exception e) {
System.out.println(e.toString());
return 0;
} finally {
System.out.println("finally执行...");
}
}
}
结果输出:
奇数
finally执行...
1
【结论】
无论是否有异常/是否return,finally都会执行。
finally与return测试例子2:
public class TestFinally2 {
public static void main(String[] args) {
System.out.println( ma() ); // b为2或者0,结果都是 30
}
public static int ma() {
int b = 2;
//int b = 0;
try {
int n = 10;
return b=n/b; // return 后的表达式一定会被执行
} catch (Exception e) {
System.out.println("###:" + b);
return 20;
} finally {
System.out.println("@@@:" + b); // 10/2=5
return 30;
}
}
}
当b=2时输出:
@@@:5
30
当b=0时输出:
###:0
@@@:0
30
【结论】
return如果放表达式,表达式一定会被执行。
finally中如果有return语句,一定会作为最终的方法返回值返回。
finally与return测试例子3:
public class TestFinally3 {
public static void main(String[] args) {
System.out.println( m1() ); // 30
}
public static int m1() {
int a = 10;
try {
a = 20;
throw new RuntimeException();
} catch (Exception e) {
a = 30;
return a;
} finally {
a = 40;
}
}
}
结果输出:30
Why???或者说,如何解释呢?
此问题不能通过应用层的语法逻辑来解释,通过反编译对JVM执行的字节码指令进行分析:
Java反编译
Java中finally关键字使用分析
【结论】
在产生了异常时,异常代码块与finally代码块中都对局部变量修改的情况下,异常代码块return了,而finally代码块中对局部变量的修改则不会作为最终的返回值。
原因:通过反编译的字节码分析,方法的返回值在实际执行的return语句时,取的是栈顶的值进行返回。而finally的赋值在局部变量表中,不会成为最终返回值。