【Java基礎】異常處理與輸入輸出流

finally中的代碼執行時機

try{}語句中含有return,那麼finally還會執行嗎?如果會,那麼是什麼時候執行(return前還是return後)

在Java的異常處理中,不論什麼情形,finally中的邏輯一定會執行,也就是說try{}塊裏面有return,那麼finally同樣會執行的,執行時機就是try{}中的return 之前。同時如果try{} catch{}以及finally{}塊中都有return ,那麼最終執行的return是finaally中的return,前兩個沒有機會執行。

在正常的流程以及正常的異常處理中,finally保證一定執行,但是特殊情形,比如try{}塊中調用了exit()那麼程序就會在try{}塊中強制退出,自然不會執行finally。
另外,邏輯沒有進入try{}而發生異常或者執行退出,那麼也不會執行finally語句塊。

異常處理原理

異常是在運行時發生的非正常情況或者錯誤。當程序違反語義規則的時候,JVM就會將其表示爲一個異常並拋出,然後被拋出的異常就可以在catch{}塊中進行捕獲和處理。
Java中的異常也是對象,並且提供了所有異常的基類java.lang.Throwable。違反語義規則的情形:Java內置的寓意檢查,比如空指針異常和數組越界異常;另一種情形就是用戶自定義的異常

運行時異常和普通異常

Java中異常類分爲錯誤Error和異常Exception。其父類都是Throwable。Error表示程序出現了嚴重的錯誤,並且該錯誤不可恢復,常常導致程序直接終止,因此程序中不會對此類異常進行捕獲(因爲Error屬於必須解決的異常,是一個正確的程序中所不應該存在的)。

Exception屬於是可恢復的異常,可以進行捕獲,主要有兩種類型:檢查異常和運行時異常。 ‘
1. 檢查異常:所有繼承自Exception的非運行時異常都是檢查異常。Java編譯器會強制進行捕獲此類異常,如IO或者SQL異常。使用場景:a. 異常的發生並不會導致程序的錯誤,進行處理後可以繼續執行後續邏輯,如數據庫連接失敗並不會退出整個應用; b. 程序依賴了外部的不可靠因素,如網絡IO’
2. 運行時異常:編譯器沒有對此類異常進行強制捕獲,如果發生這種異常而代碼沒有進行捕獲的話,會交給JVM進行處理。比如空指針異常,類型轉換異常,數組越界異常,數組存儲異常,緩衝區異常,算術異常。

使用異常處理的幾個原則:
1. Java的異常屬於對象,使用了多態的概念,所以如果catch的是父類,那麼catch子類的catch{}塊就永遠不會執行,所以建議是先捕獲子類
2. 儘早拋出異常同時對捕獲的異常進行處理
3. 可以根據業務需求自定義異常類
4. 異常能處理就處理,不能處理就拋出。比如對於一些沒有很好處理方法的異常,可以直接轉型爲運行時異常拋給JVM

JavaIO流的實現機制

Java中輸入輸出都可以看做是流,流可以看做是一組有序字節的集合即數據在設備之間的傳輸。流的本質是數據的傳輸,根據吹的數據類型不同,流可以分爲兩類:字節流和字符流。
字節流是以字節8bit爲單位,字符流是以字符16bit爲單位字節流和字符流的主要區別在於字節流在處理輸入輸出數據的時候不會使用到緩存,而字符流是使用緩存的。字符流繼承自Reader和Writer抽象類,字節流繼承自InputStream和OutputStream抽象類。 Java的IO設計採用了裝飾者模式,使用這種設計模式的好處是可以在運行司動態的給對象添加一些額外的職責,比繼承的設計方式更加靈活。

Java的NIO

在非阻塞IO之前(NIO: Nonblocking IO),Java是通過傳統的Socket實現基本的網絡通信功能。傳統的網絡通信採用阻塞IO,阻塞IO不僅導致程運行效率低而且在多線程環境下還會導致大量的進程上下文切換。在1.4時引入了非阻塞IO,NIO通過Selector Channel和Buffer來實現非阻塞IO操作。
NIO實現上使用的是Reactor設計模式,可以處理多個事件源。

Java的序列化

Java中提供兩種對象持久化方式,序列化和外部序列化。
序列化:序列化是指將對象以一串字節進行描述的過程,序列化可以將對象的狀態寫在流裏面進行網絡傳輸,或者保存到文件或數據庫中,在需要的時候可以反序列化出對象。在需要進行序列化的類中實現Serializable接口。

序列化的特點:
1. 如果一個類可以被序列化,那麼其子類也是可以序列化的
2. static類型的數據屬於類,transient類型的數據屬於臨時數據,因此被聲明爲這兩種類型的數據 是不可以進行序列化的。

序列化使用場景(使用序列化會影響系統的性能,所以儘可能不用):
1. 需要將對象通過網絡來發送或者持久化到文件或者數據庫中
2. 序列化可以實現深複製-也就是通過序列化來構建一個對象

反序列化:將流轉化爲對象
序列化和反序列化的時候,每一個類都有一個serialVersioUID,在反序列化的過程中通過serialVersioUID來判斷類的兼容性,如果待序列化的對象和目標對象的serialVersioUID不同,那麼就會拋出InvalidClassException,因此爲了使序列化和反序列化正常進行,強烈建議在對需要進行序列化的類中顯式的聲明static final修飾的serialVersioUID,作用在於:
1. 提高程序運行效率,因爲如果不顯式的提供,那麼程序會需要計算得到該serialVersioUID
2. 提高程序的兼容性,因爲不同平臺計算serialVersioUID的方式可能不一樣
3. 增強版本間的兼容性,如果不顯示提供,那麼類在修改之後,可能導致新版本的類的serialVersioUID與之前不一樣,而使得序列化失敗

外部序列化:Externalizable
外部序列化與內部序列化的去唄在於序列化是內置的API,只需要實現Serializable接口即可,開發人員不需要再額外的寫序列化邏輯就可以實現對象的序列化。而外部序列化Externalizable接口中提供的兩個讀寫函數必須要開發人員來實現,因此比較複雜,但是優點是比較靈活,對需要持久化的對象可以按需序列化,相應的效率也搞一些。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章