try catch finally是我們最常用的異常處理的流程,我們都知道執行try塊**,如果有異常發生就會被相應catch捕獲到執行catch塊**,無論如何finally塊的**都會被執行。但是如果我們在try塊中加入return語句,return和finally的執行順序呢?
對此做過試驗或者從finally總會被執行的作用來說,都會認為finally在return前執行。不過,看下面的例子。
js**:
function testtry() catch (e) finally.net**:}
private int32 testtry()結果應該是1還是3呢?如果finally在return之前那應該是3啊,但是上面兩段**是執行是乙個結果:1。catch
finally
}
難道函式或方法遇到return直接返回,finally根本就沒有執行??這不是和finally總會被執行的作用矛盾嗎?
看這段**:
function testtry() catch (e) finally因為.net不允許在finally中加return,因此沒有了.net版本的這段**。}
這段js**比之前的只是在return中多了乙個return,結果應該是什麼?1 or 3?
答案是3,這又能說明什麼?它說明不管return和finally的執行順序是怎樣,finally肯定是被執行了。
那問題又來了,既然finally肯定被執行了,那我們的第一段**結果就應該是3,而不應該是1啊?
如何揭秘,我們就要借助第一段**中.net**的編譯**:
18:這其實是.net執行的真實路徑。25: catch
00000063 90 nop
26:
30: finally
31:
00000094 90 nop
00000095 58 pop eax
00000096 ff e0 jmp eax
00000098 90 nop
34: }
00000099 8b 45 bc mov eax,dword ptr [ebp-44h]
0000009c 8d 65 f4 lea esp,[ebp-0ch]
0000009f 5b pop ebx
000000a0 5e pop esi
000000a1 5f pop edi
000000a2 5d pop ebp
000000a3 c3 ret
000000a4 c7 45 e4 00 00 00 00 mov dword ptr [ebp-1ch],0
000000ab eb eb jmp 00000098
000000ad c7 45 e4 00 00 00 00 mov dword ptr [ebp-1ch],0
000000b4 eb e2 jmp 00000098
1,首先第乙個我們可以看到的是 倒數第5行的ret指令,這個是返回指令,也就是說我們表面的return其實並不是真實的方法出口的位置。
2,看下return i;的il
00000047 8b 45 c0 mov eax,dword ptr [ebp-40h]我們看到除了一些mov操作之外,並沒有中止方法執行,最後一句是jmp跳轉的指令,而這個跳轉的位址正好是finally塊的開始的位址,也就是這句執行之後去執行了finally。0000004a 89 45 bc mov dword ptr [ebp-44h],eax
0000004d 90 nop
0000004e c7 45 e0 00 00 00 00 mov dword ptr [ebp-20h],0
00000055 c7 45 e4 fc 00 00 00 mov dword ptr [ebp-1ch],0fch
0000005c 68 8d 18 e5 03 push 3e5188dh
00000061 eb 29 jmp 0000008c
4,接著上一塊來說,我們可以看到每次操作i值時,都會有mov dword ptr [ebp-40h] 這樣的操作,也就是說這塊位址儲存的是i的值。那麼我們從return i;的il**可以看到它首先執行了兩個操作:把[ebp-40h]的值給eax,然後又把eax值給了[ebp-44h],也就是其實返回值儲存在了[ebp-44h]這個位址。
5,到最後,只是把[ebp-44h]這個位址的值放到資料暫存器,最後被呼叫者獲取。
從此真相大白,也就是變數和返回值是分別儲存在兩個不同的地方,return i;時只用i值填充返回值的位址,finally時再次改變i的值,卻不會影響返回值。至於js finally裡能再次return i;也可能是再次修改了返回值那塊位址所儲存的值。
對於值型別,分配的位址儲存直接是值,再次修改i值不能影響到返回值;而對於引用型別,位址裡儲存的是指標,是不是應該是另一番光景呢?
function testtry2() ;大膽猜一次返回的物件的i的值吧,對,就是3.o.i = 0;
try catch (e) finally
}
鑽完收工。
鑽牛角尖的成因和如何克服
為什麼會鑽牛角尖的5大因素 1 心理消極。想不開的人往往表現為性格內向,情緒消沉,自信心不足,喜歡以消極的態度看待事物,對事物的結局估計悲觀。2 偏執人格。想不開的人往往把思維停留在某一點上,不輕易改變自己的態度和認識,並沿著偏執認識走下去,甚至碰得頭破血流也不回頭。3 固定思維。想不開的人思考問題...
遞迴思想(鑽出牛角尖)
遞迴思想 函式中呼叫函式並使用返回值 經典案例 快速指數 目的 求值的整數次冪的聰明演算法 規格說明 利用遞迴的方法減少運算計算出整數次冪 整數冪的運算法則 a 4 a x a x a x a 也可以寫成a 4 a 2 x a 2 如果是奇數冪的 a 5 a 2 x a 2 x a 我們可以利用這種...
php的要注意的一些小細節和牛角尖
轉義 單引號只轉義 和 其他的不轉義 變數解析 雙引號裡面變數是可以解析的 速度 單引號不需要解析串內有沒有變數,需要轉義的內容也少,速度快點 heredoc 類似雙引號 和newdoc 類似單引號 的區別類似 如果不宣告鍵,會從0,1,2,遞增來生成鍵 array a b c 如果已存在某乙個或者...