平時你們try…catch…finally語句用的很多,知道finally塊必定會在try…catch..執行結束時執行,可是具體是在何時執行呢,今天咱們一塊兒來看下。html
public static int test1(){ int i = 0; try{ return ++i; }finally{ ++i; } }
上面的方法,執行結果返回1。finally塊中的代碼會不會沒有執行,咱們再試試。java
public static int test2(){ int i = 0; try{ return ++i; }finally{ return ++i; } }
test2()執行結果返回2。能夠確定的是,finally塊執行了。咱們對比test1()和test2(),能夠得出以下結論:
1. finally塊會在try塊return語句執行後,執行結果返回前執行;
2. 若是finally塊中有return語句,而且是返回的是值類型,則會覆蓋try塊的return結果。
那麼,若是返回的不是值,而是對象呢?
public static Integer test3(){ Map<Integer,Integer> map = new HashMap<>(); map.put(0, new Integer(0)); try{ map.put(0, new Integer(1)); return map.get(0); }finally{ map.put(0, new Integer(2)); } } public static Integer test4(){ Map<Integer,Integer> map = new HashMap<>(); map.put(0, new Integer(0)); try{ map.put(0, new Integer(1)); return map.get(0); }finally{ map = null; } }
顯然,finally塊確定執行了,可是test3()和test4()返回的均是1。咱們將test3()稍微修改下,改爲下面的test5(),
而後執行System.out.println(test5().get(0)),會發現執行結果是2.
public static Map<Integer,Integer> test5(){ Map<Integer,Integer> map = new HashMap<>(); map.put(0, new Integer(0)); try{ map.put(0, new Integer(1)); return map; }finally{ map.put(0, new Integer(2)); } }
對比test3(),test4(),test5()的代碼和返回結果,估計你們都發現了,這其實仍是java的值傳遞問題,只是平時可能做爲形參出現的更多些,這裏是做爲返回值。
當返回的是引用地址時,只有finally塊中修改的是返回地址對象內的屬性,try塊的return結果纔會被修改。方法test5(),返回map對象的引用地址,finally塊中對map作的修改,影響到try塊return的map;而test3()和test4(),返回的是Integer對象的引用地址,finally塊中對map作的修改,並不會對其有影響(從jvm內存模型的角度去看,會更好理解,但是圖我不知道怎麼畫會比較形象[難過])。
本文中的方法demo中都沒有catch,可是catch塊對於finally塊,和try是同樣的,有興趣的朋友能夠試試。