final finally finalize的区别
1.final
final修饰符 所标记的成分具有终态的特征,表示最终的意思。
final修饰类,类不能被继承。该类将不具有子类。
final修饰方法,方法不能被重写,在某些特殊情况下jvm会将该类方法直接内联以便于减少函数调用开销,新版本的Jdk并不会以此为优化方式,所以只有当明确该方法不能被子类修改(重写)的时候才使用该关键字
final修饰变量, 如果是基本数据类型,这该数据在初始化后就无法更改其值。如果是引用类型的变量,初始化完成后该变量的引用无法指向其他对象。
2. finally
finally 是指用于try{}中必须被执行的部分。
1.常规用法
try{
xxx
}catch(Exception e){
xxx
}finally{
xxx
}
2.finally特殊状态
如果return 在finally中则finally中的代码优先于try块中执行
private String finallyReturnTest(){
try {
return "return try";
} finally {
return "return finally";
}
}
结果:
return finally
从以上运行结果可以看出,当finally块中有return语句时,将会覆盖函数中其他return语句。
final的finally返回对象。
@Test
public void testString() {
System.out.println(finallyString());
}
private String finallyString() {
String str = "Hello";
try {
return str;
} finally {
str = "world";
System.out.println("finall执行了");
}
}
结果:
finall执行了
Hello
程序在执行到return时会首先将返回值存储在一个指定的位置,其次去执行finally块,最后再返回。在方法testFinally1中调用return前,先把result的值1存储在一个指定的位置,然后再去执行finally块中的代码,此时修改result的值将不会影响到程序的返回结果。
对于常规类型也是这样的。
private int finallyInt(){
int x = 10;
try{
return x;
}finally {
x = 2;
System.out.println("finally执行了");
}
}
结果:
finall执行了
10
但是,如果该对象为引用类型,那么方法返回的只是一个对象的引用。所以会改该值。
private StringBuffer finallyStringBuffer(){
StringBuffer sb = new StringBuffer("Hello");
try{
return sb;
}finally {
sb.append(" World");
System.out.println("finally 我被执行了");
}
}
结果:
finally 我被执行了
Hello World
如果在finally里return,那么finally赋值操作是有效的。
private String finallyStringReturn() {
String str = "Hello";
try {
return str;
} finally {
str = str + "World";
return str;
}
}
结果:
Hello World
下面总结下finally执行顺序。
- finally 和try中同时发现return ,finally会强制覆盖try中的return。
- try中return的如果是final修饰的变量,或者是常规变量,则finally块里的赋值操作无效。先出方法栈然后执行。
- 如果try中return的是非finall修饰引用变量,finally里的赋值会改变引用的内容。
- 如果在finally里return,那么finally赋值操作是有效的。
finalize
finalize 是一个Object对象的方法,当一个对象被回收时会调用该方法。
常规用法
public class Test {
@Override
protected void finalize() throws Throwable {
System.out.println("我被回收了");
super.finalize();
}
}
public class Demo {
public static void main(String[] args) {
Test test = new Test();
test = null;
//这里的gc调用不是每次都会成功。
System.gc();
//简易的增加一个延迟
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果
我被回收了