异常处理关键字
Java异常处理机制用到的几个关键字:try、catch、finally、throw、throws。
- try:用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
- catch:用于捕获异常。catch用来捕获try语句块中发生的异常。
- finally:finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
- throw:用于抛出异常。
- throws:用在方法签名中,用于声明该方法可能抛出的异常。
final、finally、finalize的区别与用法
final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
finally:是异常处理语句结构的一部分,表示总是执行。
finalize:是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等。
Try-with-resources
环境
Java1.7版本及其以后版本
语法
JDK1.7开始,java引入了 try-with-resources
声明,将 try-catch-finally
简化为 try-catch
,这其实是一种语法糖,在编译时会进行转化为 try-catch-finally
语句。
新的声明包含三部分:try-with-resources 声明、try 块、catch 块。它要求在 try-with-resources
声明中定义的变量实现了 AutoCloseable
接口,这样在系统可以自动调用它们的close方法,从而替代了finally中关闭资源的功能。
所有实现了 java.lang.AutoCloseable
接口(其中,它包括实现了java.io.Closeable
的所有对象),可以使用作为资源。
try-with-resources
声明在 JDK 9 得到改进。如果你已经有一个资源是 final 或等效于 final 变量,您可以在try-with-resources
语句中使用该变量,而无需在try-with-resources
语句中声明一个新变量。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
public class Tester {
public static void main(String[] args) throws IOException {
System.out.println(readData("test"));
}
static String readData(String message) throws IOException {
Reader inputString = new StringReader(message);
BufferedReader br = new BufferedReader(inputString);
try (br) {//在 Java 9 中,不需要声明资源 br就可以使用它,并得到相同的结果。
return br.readLine();
}
}
}
作用
关闭在try-catch语句块中使用的资源,需要在ry-with-resources 声明中的实现AutoCloseable 接口的资源。
使用范例
Java1.7之前写法
public static void main(String[] args) {
FileInputStream file = null;
try {
file = new FileInputStream("D:\\logs\\log-cleaner.log");
System.out.println("ooo");
file.read();
System.out.println("aaa");
} catch (IOException io) {
System.out.println("bbb");
io.printStackTrace();
} catch (Exception e) {
System.out.println("ccc");
e.printStackTrace();
} finally {
if (file != null) {
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用JDK1.9之前的 try-with-resources异常处理机制
public static void main(String[] args) {
try(FileInputStream file = new FileInputStream("D:\\logs\\log-cleaner.log")){
System.out.println("ooo");
file.read();
System.out.println("aaa");
}catch (IOException io){
System.out.println("bbb");
io.printStackTrace();
}catch (Exception e){
System.out.println("ccc");
e.printStackTrace();
}
}
编译后的class文件
public static void main(String[] paramArrayOfString)
{
try
{
FileInputStream localFileInputStream = new FileInputStream("D:\\logs\\log-cleaner.log");
Object localObject1 = null;
try {
System.out.println("ooo");
localFileInputStream.read();
System.out.println("aaa");
}
catch (Throwable localThrowable2)
{
localObject1 = localThrowable2; throw localThrowable2;
}
finally
{
if (localFileInputStream != null) if (localObject1 != null) try { localFileInputStream.close(); } catch (Throwable localThrowable3) { localObject1.addSuppressed(localThrowable3); } else localFileInputStream.close();
}
} catch (IOException localIOException) {
System.out.println("bbb");
localIOException.printStackTrace();
} catch (Exception localException) {
System.out.println("ccc");
localException.printStackTrace();
}
}
return与finally的执行顺序
public class TestException {
public static void main(String[] args) {
System.out.println("-------------");
System.out.println(div());//try中有return,且try中不抛异常。
/*结果:
process try
process finally
0
*/
System.out.println("-------------");
System.out.println(divE());//catch中有return,且try中抛异常。
/*结果:
process try
process catch
process finally
2
*/
System.out.println("-------------");
System.out.println(divEr());//catch,finally中都有return,且try中抛异常。
/*
process try
process catch
process finally
3
*/
}
public static int div() {
int result = 0;
try {
System.out.println("process try");
return result;//如果try和catch的return是一个变量时且函数的是从其中一个返回时,后面finally中语句即使有对返回的变量进行赋值的操作时,也不会影响返回的值。
} catch (ArithmeticException e) {
result = 2;
System.out.println("process catch");//
} finally {
result = 3;//finally中语句对返回的变量进行赋值的操作时,也不会影响返回的值
System.out.println("process finally");//
}
return result;
}
public static int divE() {
int result = 0;
try {
System.out.println("process try");
int proces = 1/0;
return result;
} catch (ArithmeticException e) {
result = 2;
System.out.println("process catch");
return result;//如果try和catch的return是一个变量时且函数的是从其中一个返回时,后面finally中语句即使有对返回的变量进行赋值的操作时,也不会影响返回的值。
} finally {
result = 3;//finally中语句对返回的变量进行赋值的操作时,也不会影响返回的值
System.out.println("process finally");
}
}
public static int divEr() {
int result = 0;
try {
System.out.println("process try");
result = 1/0;
return result;
} catch (ArithmeticException e) {
result = 2;
System.out.println("process catch");
// throw new ArithmeticException("divEr执行异常");// finally 里有return,这里throw失效
return result;// finally 里有return,这里return失效
} finally {
result = 3;
System.out.println("process finally");
return result;//finally块中的return语句会阻止异常的栈调用传输,使divEr认为该方法已经正常返回
}
}
}
通过上面代码可以得出结论:
- 当finally有返回值时,会直接返回。不会再去返回try或者catch中的返回值。
- 如果try和catch的return是一个变量时且函数的是从其中一个返回时,后面finally中语句即使有对返回的变量进行赋值的操作时,也不会影响返回的值。
原因通过反编译插件查看Class文件:
网友评论