異常處理關(guān)鍵字
Java異常處理機(jī)制用到的幾個關(guān)鍵字:try、catch戈钢、finally、throw、throws。
- try:用于監(jiān)聽危喉。將要被監(jiān)聽的代碼(可能拋出異常的代碼)放在try語句塊之內(nèi)驼唱,當(dāng)try語句塊內(nèi)發(fā)生異常時彤委,異常就被拋出铐尚。
- catch:用于捕獲異常拨脉。catch用來捕獲try語句塊中發(fā)生的異常。
- finally:finally語句塊總是會被執(zhí)行宣增。它主要用于回收在try塊里打開的物力資源(如數(shù)據(jù)庫連接玫膀、網(wǎng)絡(luò)連接和磁盤文件)。只有finally塊爹脾,執(zhí)行完成之后匆骗,才會回來執(zhí)行try或者catch塊中的return或者throw語句,如果finally中使用了return或者throw等終止方法的語句誉简,則就不會跳回執(zhí)行碉就,直接停止。
- throw:用于拋出異常闷串。
- throws:用在方法簽名中瓮钥,用于聲明該方法可能拋出的異常。
final烹吵、finally碉熄、finalize的區(qū)別與用法
final:用于聲明屬性,方法和類肋拔,分別表示屬性不可變锈津,方法不可覆蓋,類不可繼承凉蜂。
finally:是異常處理語句結(jié)構(gòu)的一部分琼梆,表示總是執(zhí)行。
finalize:是Object類的一個方法窿吩,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法茎杂,供垃圾收集時的其他資源回收,例如關(guān)閉文件等纫雁。
Try-with-resources
環(huán)境
Java1.7版本及其以后版本
語法
JDK1.7開始煌往,java引入了 try-with-resources
聲明,將 try-catch-finally
簡化為 try-catch
轧邪,這其實(shí)是一種語法糖刽脖,在編譯時會進(jìn)行轉(zhuǎn)化為 try-catch-finally
語句。
新的聲明包含三部分:try-with-resources 聲明忌愚、try 塊曲管、catch 塊。它要求在 try-with-resources
聲明中定義的變量實(shí)現(xiàn)了 AutoCloseable
接口菜循,這樣在系統(tǒng)可以自動調(diào)用它們的close方法翘地,從而替代了finally中關(guān)閉資源的功能。
所有實(shí)現(xiàn)了 java.lang.AutoCloseable
接口(其中癌幕,它包括實(shí)現(xiàn)了java.io.Closeable
的所有對象)衙耕,可以使用作為資源。
try-with-resources
聲明在 JDK 9 得到改進(jìn)勺远。如果你已經(jīng)有一個資源是 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就可以使用它厅瞎,并得到相同的結(jié)果。
return br.readLine();
}
}
}
作用
關(guān)閉在try-catch語句塊中使用的資源初坠,需要在ry-with-resources 聲明中的實(shí)現(xiàn)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異常處理機(jī)制
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的執(zhí)行順序
public class TestException {
public static void main(String[] args) {
System.out.println("-------------");
System.out.println(div());//try中有return,且try中不拋異常碟刺。
/*結(jié)果:
process try
process finally
0
*/
System.out.println("-------------");
System.out.println(divE());//catch中有return锁保,且try中拋異常。
/*結(jié)果:
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是一個變量時且函數(shù)的是從其中一個返回時者填,后面finally中語句即使有對返回的變量進(jìn)行賦值的操作時浩村,也不會影響返回的值。
} catch (ArithmeticException e) {
result = 2;
System.out.println("process catch");//
} finally {
result = 3;//finally中語句對返回的變量進(jìn)行賦值的操作時占哟,也不會影響返回的值
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是一個變量時且函數(shù)的是從其中一個返回時心墅,后面finally中語句即使有對返回的變量進(jìn)行賦值的操作時,也不會影響返回的值榨乎。
} finally {
result = 3;//finally中語句對返回的變量進(jìn)行賦值的操作時嗓化,也不會影響返回的值
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執(zhí)行異常");// finally 里有return,這里throw失效
return result;// finally 里有return谬哀,這里return失效
} finally {
result = 3;
System.out.println("process finally");
return result;//finally塊中的return語句會阻止異常的棧調(diào)用傳輸刺覆,使divEr認(rèn)為該方法已經(jīng)正常返回
}
}
}
通過上面代碼可以得出結(jié)論:
- 當(dāng)finally有返回值時,會直接返回史煎。不會再去返回try或者catch中的返回值谦屑。
- 如果try和catch的return是一個變量時且函數(shù)的是從其中一個返回時,后面finally中語句即使有對返回的變量進(jìn)行賦值的操作時篇梭,也不會影響返回的值氢橙。
原因通過反編譯插件查看Class文件: