java magic翻譯系列文章,java小伙伴不知道的奇妙世界
Java Magic. Part 3: Finally
@(Base)[JDK, magic, 黑魔法]
轉載請寫明:原文地址
英文原文
系列文章:
-Java Magic. Part 1: java.net.URL
-Java Magic. Part 2: 0xCAFEBABE
-Java Magic. Part 3: Finally
-Java Magic. Part 4: sun.misc.Unsafe
所有JAVA程式員都應該知道一個基本概念-finally一定會被執行,但是真的是這樣麽?
這取決於“執行”是什麼意思。但總的來說答案都是,YES。
Normal program execution
有人可能拿如下的例子來反駁:
try {
System.exit(1);
} finally {
System.out.println("I'm here, man");
}
剛纔是不是你說的finlly塊一定會被執行。
顯然在上面這個例子中,Sout
語句不會被執行。我們剛纔也說了,是正常的程式六層中答案是肯定的。
下麵這句話來自官方文檔
Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute.
我們再看下麵這段代碼,第二行是不是一定會執行呢?
Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute.
答案仍然是肯定的。除非...BANG...斷電了,程式終止。
這是神馬意思呢?意思就是程式非正常的運行。我們沒辦法保證所有事情。顯然,這和System.exit(1)
是一個意思,也和你電腦上的重啟鍵是一個意思。
所以我們不討論這種情況啦。沒勁。
Perpetuum Mobile
永動機 我們再來看如下代碼:
try {
while (true) {
System.out.println("I print here some useful information");
}
} finally {
System.out.println("Let me run");
}
這裡的finlly塊會執行嗎?當然可能,就是在標準輸出異常的時候。但是絕大部分情況答案仍然是不會。
Threads
什麼是線程?我們都知道線程的執行流程可以被interrupted。
假設我們有一個線程正在執行一些東西,另外一個線程kill掉當前線程(此時他正要執行finally)。
還有一個場景是,如果兩個線程之間有死鎖,那麼還是不會執行finally塊的。
下麵這段話仍然來自官方文檔
...if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.
所以這種情況下,我們可以把線程當做一個獨立的程式來看:
Finally塊肯定是會執行的。除了程式或者線程異常的終止了。
Finally we return
好了,根據上述的文字,我們瞭解了finally一定會被執行。但是你知道finally什麼時候會被執行嗎?
考慮如下代碼:
int someFunc() {
try {
return 0;
} finally {
return 1;
}
}
這個返回值是多少呢? 返回值是1
。因為finally
一定會被執行。
考慮下麵這段呢?
int someFunc() {
try {
throw new RuntimeException();
} finally {
return 1;
}
}
答案仍然是1。但是有個問題是,異常就被吞掉了。這個場景是一個非常有名的場景,叫做exception swallowing
。這是一個非常危險示例,因為client的代碼以為你會返回一個值或者拋出一個異常,但是你永遠都只是返回一個值。
下麵我們最後看一個類似的例子:
String deposit(int amount) throws DAOException {
try {
return dao.deposit(amount);
} finally {
return "OK";
}
}
dao.deposit
會拋出一個受檢的異常,導致客戶端必須處理這個異常,但是呢,由於上面我們已經提到的原因,這個函數又永遠返回OK
,是不是有點淡淡的憂傷。
所以我們得到另外一個結論:
永遠不要在finally
裡面使用return
語句。
Instead of conclusion
很多程式員已經意識到finally的一些問題。但根據我們上面說的,只需要註意兩點就可以避免犯錯~
- Rule 1 Finally executes always, except the case where controlling program or thread was aborted.
- Rule 2 Never use return from finally block.