Java異常謎題36:優(yōu)柔寡斷

字號(hào):

下面這個(gè)可憐的小程序并不能很好地做出其自己的決定。它的decision方法將返回true,但是它還返回了false。那么,它到底打印的是什么呢?甚至,它是合法的嗎?
    public class Indecisive {
     public static void main(String[] args) {
     System.out.println(decision());
     }
     static boolean decision() {
     try {
     return true;
     } finally {
     return false;
     }
     }
    }
    你可能會(huì)認(rèn)為這個(gè)程序是不合法的。畢竟,decision方法不能同時(shí)返回true和false。如果你嘗試一下,就會(huì)發(fā)現(xiàn)它編譯時(shí)沒(méi)有任何錯(cuò)誤,并且它所打印的是false。為什么呢?
    原因就是在一個(gè)try-finally語(yǔ)句中,finally語(yǔ)句塊總是在控制權(quán)離開(kāi)try語(yǔ)句塊時(shí)執(zhí)行的[JLS 14.20.2]。無(wú)論try語(yǔ)句塊是正常結(jié)束的,還是意外結(jié)束的,情況都是如此。一條語(yǔ)句或一個(gè)語(yǔ)句塊在它拋出了一個(gè)異常,或者對(duì)某個(gè)封閉型語(yǔ)句執(zhí)行了一個(gè)break或continue,或是象這個(gè)程序一樣在方法中執(zhí)行了一個(gè)return時(shí),將發(fā)生意外結(jié)束。它們之所以被稱(chēng)為意外結(jié)束,是因?yàn)樗鼈冏柚钩绦蛉グ错樞驁?zhí)行下面的語(yǔ)句。
    當(dāng)try語(yǔ)句塊和finally語(yǔ)句塊都意外結(jié)束時(shí),在try語(yǔ)句塊中引發(fā)意外結(jié)束的原因?qū)⒈粊G棄,而整個(gè)try-finally語(yǔ)句意外結(jié)束的原因?qū)⒂趂inally語(yǔ)句塊意外結(jié)束的原因相同。在這個(gè)程序中,在try語(yǔ)句塊中的return語(yǔ)句所引發(fā)的意外結(jié)束將被丟棄,而try-finally語(yǔ)句意外結(jié)束是由finally語(yǔ)句塊中的return造成的。簡(jiǎn)單地講,程序嘗試著(try)返回(return)true,但是它最終(finally)返回(return)的是false。
    丟棄意外結(jié)束的原因幾乎永遠(yuǎn)都不是你想要的行為,因?yàn)橐馔饨Y(jié)束的最初原因可能對(duì)程序的行為來(lái)說(shuō)會(huì)顯得更重要。對(duì)于那些在try語(yǔ)句塊中執(zhí)行break、continue或return語(yǔ)句,只是為了使其行為被finally語(yǔ)句塊所否決掉的程序,要理解其行為是特別困難的。
    總之,每一個(gè)finally語(yǔ)句塊都應(yīng)該正常結(jié)束,除非拋出的是不受檢查的異常。千萬(wàn)不要用一個(gè)return、break、continue或throw來(lái)退出一個(gè)finally語(yǔ)句塊,并且千萬(wàn)不要允許將一個(gè)受檢查的異常傳播到一個(gè)finally語(yǔ)句塊之外去。
    對(duì)于語(yǔ)言設(shè)計(jì)者,也許應(yīng)該要求finally語(yǔ)句塊在未出現(xiàn)不受檢查的異常時(shí)必須正常結(jié)束。朝著這個(gè)目標(biāo),try-finally結(jié)構(gòu)將要求finally語(yǔ)句塊可以正常結(jié)束[JLS 14.21]。return、break或continue語(yǔ)句把控制權(quán)傳遞到finally語(yǔ)句塊之外應(yīng)該是被禁止的,任何可以引發(fā)將被檢查異常傳播到finally語(yǔ)句塊之外的語(yǔ)句也同樣應(yīng)該是被禁止的。