public static String test() {
try {
System.out.println("try");
return "return in try";
} catch(Exception e) {
System.out.println("catch");
return "return in catch";
} finally {
System.out.println("finally");
return "return in finally";
}
}
調用test()的結果:jvm
try
finally
return in finally
public static String test() {
try {
System.out.println("try");
return "return in try";
} catch(Exception e) {
System.out.println("catch");
} finally {
System.out.println("finally");
}
return "return in function";
}
調用test()的結果:ide
try
finally
return in try
public static String test() {
try {
System.out.println("try");
throw new Exception();
} catch(Exception e) {
System.out.println("catch");
return "return in catch";
} finally {
System.out.println("finally");
return "return in finally";
}
}
調用test()的結果:函數
try
catch
finally
return in finally
public static String test() {
try {
System.out.println("try");
throw new Exception();
} catch(Exception e) {
System.out.println("catch");
return "return in catch";
} finally {
System.out.println("finally");
}
}
調用test()的結果:oop
try
catch
finally
return in catch
public static String test() {
try {
System.out.println("try");
throw new Exception();
} catch(Exception e) {
System.out.println("catch");
} finally {
System.out.println("finally");
}
return "return in function";
}
調用test()的結果:優化
try
catch
finally
return in function
上面這幾個例子,大多數人已經很是瞭解。同時也衍生出一些理論,好比不要在finally中return等,再也不贅述。atom
public static int test() {
try {
return 1;
} finally {
return 2;
}
}
返回值:2spa
說明:與咱們上面的例子一致,finally中的return致使提早返回,try中的return1不會被執行。.net
附編譯後的代碼:orm
public static int test() {
try {
boolean var0 = true;
return 2;
} finally {
;
}
}
能夠看到編譯器作過優化,同時驗證了boolean類型在底層是用int實現的,但注意你在源碼中直接給int行賦值true或false是不被容許的。對象
public static int test() {
int i;
try {
i = 3;
} finally {
i = 5;
}
return i;
}
返回值:5
說明:執行try中的代碼後,再執行finally中的代碼,最終i被賦值爲5,最後返回
附編譯後的代碼:
public static int test() {
boolean var0 = true;
byte i;
try {
var0 = true;
} finally {
i = 5;
}
return i;
}
一樣能夠看出,編譯器作了一些優化。
public static int test() {
int i = 1;
try {
i = 3;
return i;
} finally {
i = 5;
}
}
返回值:3
這個例子稍微有點意思,按咱們一般的思惟,應該仍是返回5,畢竟finally中把i賦值爲5了嘛,而後由try中的return返回。然而很不幸,返回值是3。
爲何呢?先看一下編譯後的代碼:
public static int test() {
boolean var0 = true;
byte var1;
try {
int i = 3;
var1 = i;
} finally {
var0 = true;
}
return var1;
}
咱們會發現,finally中的代碼塊不起做用。不知你是否想起一點:Java中是按值傳遞的,finally中的i只是一個局部變量,finally塊執行完畢後,局部變量便不復存在。
接着看例子:
public static List test() {
List<Integer> list = new ArrayList<>();
try {
list.add(1);
return list;
} finally {
list.add(2);
}
}
返回:包含1和2兩個元素的List對象。
說明:這個例子中,基本類型int被替換爲引用類型List,雖然list是按值傳遞,但它內部的狀態可變(體如今這裏,就是能夠add元素)。擴展:finally只能保證對象自己不可變,但沒法保證對象內部狀態不可變。
附編譯後的代碼:
public static List test() {
ArrayList list = new ArrayList();
ArrayList var1;
try {
list.add(1);
var1 = list; // 執行這一步操做後,var1和list指向同一個對象
} finally {
list.add(2);
}
return var1;
}
你如今應該以爲本身理解了,那麼再來看兩個例子:
public static int test() {
try {
System.exit(0);
} finally {
return 2;
}
}
該函數沒有返回值。緣由:jvm提早退出了。
附編譯後的代碼:
public static int test() {
try {
System.exit(0);
return 2;
} finally {
;
}
}
public static int test() {
try {
while(true) {
System.out.println("Infinite loop.");
}
} finally {
return 2;
}
}
因爲try中的無限循環阻塞,永遠執行不到finally中的代碼塊。
附編譯後的代碼:
public static int test() {
try {
while(true) {
System.out.println("Infinite loop.");
}
} finally {
;
}
}
爲了方便說明,只舉了finally代碼塊的例子,catch代碼塊是相似的。
執行順序:
1. try代碼塊中return前面的部分
2. catch代碼塊中return前面的部分
3. finally代碼塊中return前面的部分
4. finally的return 或 catch的return 或 try的return。若前面的return被執行,會致使提早返回,同時後面的return被忽略。
5. 方法的其餘部分
變量:
注意Java的按值傳遞規則
特殊狀況:
注意finally不會被執行的狀況