1.finall塊什么時(shí)候執(zhí)行
在Java的異常處理中,finally塊的作用就是為了保證無論出現(xiàn)什么情況鹊漠,finally塊里的代碼一定會被執(zhí)行主到。由于程序執(zhí)行return就意味著結(jié)束對當(dāng)前函數(shù)的調(diào)用并跳出這個(gè)函數(shù)體,因此任何語句要執(zhí)行都只能在return執(zhí)行躯概,除非碰到exit函數(shù)登钥,因此finally塊里的代碼也是在return前執(zhí)行的。此外娶靡,如果try-catch-finally塊中都有return牧牢,那么finally中的return語句將會覆蓋別處的return語句,最終返回到調(diào)用者那里的是finally中return的值姿锭。
此外由于f在一個(gè)方法內(nèi)部定義的變量都存儲在棧中塔鳍,當(dāng)這個(gè)函數(shù)結(jié)束后,其對應(yīng)的棧就被回收呻此,此時(shí)在其他方法中定義的變量將不存在了轮纫,因此return在返回時(shí)不時(shí)直接返回變量值,而是復(fù)制一份然后返回焚鲜。因此對于基本類型的數(shù)據(jù)掌唾,在finallly塊中改變r(jià)eturn的值對返回值沒有任何影響放前,但是對引用類型的數(shù)據(jù)會有影響。
注:finally塊是不是一定會被執(zhí)行糯彬?(不一定)
- 當(dāng)程序在進(jìn)入try語句塊之前就出現(xiàn)異常時(shí)凭语,會直接結(jié)束,不會執(zhí)行finally塊中代碼撩扒。
- 在try塊中強(qiáng)制退出時(shí)不會執(zhí)行finally塊中的代碼似扔。
2.異常處理
異常時(shí)指程序運(yùn)行時(shí)(非編譯時(shí))所發(fā)生的非正常情況或錯(cuò)誤,當(dāng)程序違反了語義規(guī)則時(shí)却舀,JVM就會將出現(xiàn)的錯(cuò)誤表示為一個(gè)異常并拋出虫几,才catch程序塊中進(jìn)行捕獲和處理。
在Java的API中挽拔,定義了很多異常類辆脸,這些異常類分為Error(錯(cuò)誤)和Exception(異常)兩大類。
違反語義規(guī)則包括兩種情況:一種是Java類庫內(nèi)置的語義檢查螃诅,例如數(shù)組下標(biāo)越界時(shí)啡氢,會一發(fā)IndexOutOfBoundsException;另一種情況是Java允許開發(fā)人員擴(kuò)展這種語義檢查术裸,開發(fā)人員創(chuàng)建自己的異常類倘是,并自由選擇何時(shí)用throw關(guān)鍵字拋出。
3.運(yùn)行時(shí)異常和普通異常的區(qū)別
Java提供了兩種錯(cuò)誤的異常類:Error和Exception袭艺,且它們擁有共同的父類Throwable搀崭。
- Error表示程序在運(yùn)行期間表現(xiàn)了非常嚴(yán)重的錯(cuò)誤,并且錯(cuò)誤是不可恢復(fù)的由于這屬于JVM層次的嚴(yán)重錯(cuò)誤猾编,因此這種錯(cuò)誤是會導(dǎo)致程序終止執(zhí)行的瘤睹。OutofMemoryError、ThreadDeath等都 屬于錯(cuò)誤答倡。
- Exception表示可恢復(fù)異常轰传,是編譯器可以捕捉到的,包含兩種類型:檢查異常(checked exception)和運(yùn)行時(shí)異常(runtime exception)瘪撇。
-
檢查異常是程序中最經(jīng)常碰到的異常获茬。所有繼承自Exception并且不是運(yùn)行時(shí)異常的異常都是檢查異常,比如最常見的IO異常和SQL異常倔既。這種異常發(fā)生在編譯階段恕曲,Java編譯器強(qiáng)制程序去捕獲次類型的異常,即try-catch渤涌。這種異常一般用在如下情況:
- 異常的發(fā)生并不會導(dǎo)致程序出錯(cuò)码俩,進(jìn)行處理后可以繼續(xù)執(zhí)行后續(xù)的操作,如連接數(shù)據(jù)庫失敗后歼捏,可以重連稿存。
- 程序依賴于不可靠的外部條件,如系統(tǒng)的IO瞳秽。
運(yùn)行時(shí)異常
對于運(yùn)行時(shí)異常瓣履,編譯器沒有強(qiáng)制對其進(jìn)行捕獲并處理。如果不對這種異常進(jìn)行處理练俐,當(dāng)出現(xiàn)這種異常時(shí)袖迎,會由JVM來處理,例如NUllPointerException(空指針)異常腺晾、ClassCastException(類型轉(zhuǎn)換異常)燕锥、ArrayIndexOutOfBoundsException(數(shù)組越界異常)、ArrayStoreExcption(數(shù)組存儲異常)悯蝉、BufferOverflowException(緩沖區(qū)溢出異常)归形、ArithmeticException(算術(shù)異常),它就是運(yùn)行時(shí)異常鼻由。出現(xiàn)運(yùn)行時(shí)異常時(shí)暇榴,系統(tǒng)會把異常一直往上層拋出,直到遇到處理代碼為止蕉世。
-
注:
- Java異常處理用到了多態(tài)的概念蔼紧,如果在異常處理過程中,先捕獲了基類狠轻,然后
再捕獲子類奸例,那么捕獲子類的代碼塊將永遠(yuǎn)不會被執(zhí)行。因此在進(jìn)行異常捕獲時(shí)向楼,正確的寫法是:先捕獲子類查吊,再捕獲基類的異常信息。 - 盡早拋出異常蜜自,同時(shí)對捕獲的異常進(jìn)行處理菩貌,或者從錯(cuò)誤中回復(fù),或者讓程序繼續(xù)執(zhí)行重荠。對于有些異常類型箭阶,例如運(yùn)行時(shí)異常,實(shí)際上根本不必處理戈鲁。
- 可以根據(jù)實(shí)際的需求自定義異常類仇参,這些自定義的異常類只要繼承自Exception類即可。
- 異常能處理就處理婆殿,不能處理就拋出诈乒。對于一般異常,如果不能進(jìn)行有效的處理婆芦,最好轉(zhuǎn)換為運(yùn)行時(shí)異常拋出怕磨,對于最終沒有處理的異常喂饥,JVM會進(jìn)行處理。