1. finally
通常在finally语句块中完成资源的关闭/释放,因为即使try中出现了异常finally中的代码一定会执行。
下列程序空指针异常后会跳过流的关闭代码,执行catch中的语句,所以该程序不安全,关闭不了流:
public static void main(String[] args) {
try {
//创建输入流对象
FileInputStream fis=new FileInputStream("D:\\downloads\\test.txt");
//开始读文件。。。
String s=null;
//这里一定会出现空指针异常
s.toString();
//流使用完之后需要关闭,即使上面的程序出现异常也要关闭
fis.close();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}
用finally进行改进:
public static void main(String[] args) {
FileInputStream fis = null;//声明位置放在try外面,这样finally中才能用
try {
//创建输入流对象
fis = new FileInputStream("D:\\downloads\\test.txt");
//开始读文件。。。
String s = null;
//这里一定会出现空指针异常
s.toString();
//流使用完之后需要关闭,即使上面的程序出现异常也要关闭
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//放在这里比较保险,finally中的语句一定会执行
//判断fis是否为空,是空指针的时候没必要关闭,不空的时候关闭
//close方法需要处理异常,用try catch
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
finally和try联用,没有catch:
try{
System.out.println("try...");
return;
//System.exit(0);只有这一条退出JVM的语句才会不执行finally
}finally{
System.out.println("finally...");
}
System.out.println("hello world!");
/*
输出:
try...
finally...
*/
即使try中有return,finally也会执行,执行顺序:打印try…–>打印finally…–>return,但hello world!不会被打印,执行不到这一步程序在return那里就结束了,打印hello world这一句会报错。
2. 面试题
public static void main(String[] args) {
int result=m();
System.out.println(result);
}
public static int m(){
int i=100;
try {
return i;
}finally {
i++;
}
}
//输出:100
解析:java语法规则规定方法体中的代码必须遵循自上而下的顺序依次逐行执行,return语句一旦执行,整个方法必须结束。虽然先执行i++,但try中的return i保存在一个临时栈中,虽然i加了1,但并没有影响临时栈中的i。
使用DJ Java Decompiler反编译工具可以看到代码执行过程为:
public static int m(){
int i=100;
int j=i;
i++;
return j;//返回的是j的值,也就是初始i的值
}
3. final、finalize、finally区别(笔试常考)
final:关键字,表示最终的不变的,可以修饰变量(常量)、方法(无法覆盖)、类(无法继承)等
finally:关键字,和try联用处理异常机制,finally语句块中的代码一定会执行
finalize:标示符,Object类中的一个方法,JVM的GC垃圾回收器负责调用