1. 程式人生 > >幾種常見的Runtime Exception

幾種常見的Runtime Exception

應用程序 正在 def 越界訪問 通知 而在 原則 轉移 也不會

    • 摘要:一,error和exception的區別,RuntimeException和非RuntimeException的區別1.異常機制 異常機制是指當程序出現錯誤後,程序如何處理。具體來說,異常機制提供了程序退出的安全通道。當出現錯誤後,程序執行的流程發生改變,程序的控制權轉移到異常處理器。 傳統的處理異常的辦法是,函數返回一個特殊的結果來表示出現異常(通
    • 一,error和exception的區別,RuntimeException和非RuntimeException的區別

      1. 異常機制
      異常機制是指當程序出現錯誤後,程序如何處理。具體來說,異常機制提供了程序退出的安全通道。當出現錯誤後,程序執行的流程發生改變,程序的控制權轉移到異常處理器。

      傳統的處理異常的辦法是,函數返回一個特殊的結果來表示出現異常(通常這個特殊結果是大家約定俗稱的),調用該函數的程序負責檢查並分析函數返回的結果。這樣做有如下的弊端:例如函數返回-1代表出現異常,但是如果函數確實要返回-1這個正確的值時就會出現混淆;可讀性降低,將程序代碼與處理異常的代碼混爹在一起;由調用函數的程序來分析錯誤,這就要求客戶程序員對庫函數有很深的了解。
      異常處理的流程:
      ① 遇到錯誤,方法立即結束,並不返回一個值;同時,拋出一個異常對象 。
      ② 調用該方法的程序也不會繼續執行下去,而是搜索一個可以處理該異常的異常處理器,並執行其中的代碼 。

      2 異常的分類
      異常的分類:
      ① 異常的繼承結構:基類為Throwable,Error和Exception繼承Throwable,RuntimeException和IOException等繼承Exception,具體的RuntimeException繼承RuntimeException。
      ② Error和RuntimeException及其子類成為未檢查異常(unchecked),其它異常成為已檢查異常(checked)。

      每個類型的異常的特點
      Error體系 :
      Error類體系描述了Java運行系統中的內部錯誤以及資源耗盡的情形。應用程序不應該拋出這種類型的對象(一般是由虛擬機拋出)。如果出現這種錯誤,除了盡力使程序安全退出外,在其他方面是無能為力的。所以,在進行程序設計時,應該更關註Exception體系。

      Exception體系包括RuntimeException體系和其他非RuntimeException的體系 :
      ① RuntimeException:RuntimeException體系包括錯誤的類型轉換、數組越界訪問和試圖訪問空指針等等。處理RuntimeException的原則是:如果出現RuntimeException,那麽一定是程序員的錯誤。例如,可以通過檢查數組下標和數組邊界來避免數組越界訪問異常。
      ②其他非RuntimeException(IOException等等):這類異常一般是外部錯誤,例如試圖從文件尾後讀取數據等,這並不是程序本身的錯誤,而是在應用環境中出現的外部錯誤。

      與C++異常分類的不同 :
      ① Java中RuntimeException這個類名起的並不恰當,因為任何異常都是運行時出現的。(在編譯時出現的錯誤並不是異常,換句話說,異常就是為了解決程序運行時出現的的錯誤)。
      ② C++中logic_error與Java中的RuntimeException是等價的,而runtime_error與Java中非RuntimeException類型的異常是等價的。
      3 異常的使用方法
      聲明方法拋出異常
      ① 語法:throws(略)
      ② 為什麽要聲明方法拋出異常?
      方法是否拋出異常與方法返回值的類型一樣重要。假設方法拋出異常卻沒有聲明該方法將拋出異常,那麽客戶程序員可以調用這個方法而且不用編寫處理異常的代碼。那麽,一旦出現異常,那麽這個異常就沒有合適的異常控制器來解決。
      ③ 為什麽拋出的異常一定是已檢查異常?
      RuntimeException與Error可以在任何代碼中產生,它們不需要由程序員顯示的拋出,一旦出現錯誤,那麽相應的異常會被自動拋出。而已檢查異常是由程序員拋出的,這分為兩種情況:客戶程序員調用會拋出異常的庫函數(庫函數的異常由庫程序員拋出);客戶程序員自己使用throw語句拋出異常。遇到Error,程序員一般是無能為力的;遇到RuntimeException,那麽一定是程序存在邏輯錯誤,要對程序進行修改(相當於調試的一種方法);只有已檢查異常才是程序員所關心的,程序應該且僅應該拋出或處理已檢查異常。
      註意:覆蓋父類某方法的子類方法不能拋出比父類方法更多的異常,所以,有時設計父類的方法時會聲明拋出異常,但實際的實現方法的代碼卻並不拋出異常,這樣做的目的就是為了方便子類方法覆蓋父類方法時可以拋出異常。

      如何拋出異常
      ① 語法:throw(略)
      ② 拋出什麽異常?對於一個異常對象,真正有用的信息時異常的對象類型,而異常對象本身毫無意義。比如一個異常對象的類型是ClassCastException,那麽這個類名就是唯一有用的信息。所以,在選擇拋出什麽異常時,最關鍵的就是選擇異常的類名能夠明確說明異常情況的類。
      ③ 異常對象通常有兩種構造函數:一種是無參數的構造函數;另一種是帶一個字符串的構造函數,這個字符串將作為這個異常對象除了類型名以外的額外說明。
      ④ 創建自己的異常:當Java內置的異常都不能明確的說明異常情況的時候,需要創建自己的異常。需要註意的是,唯一有用的就是類型名這個信息,所以不要在異常類的設計上花費精力。

      捕獲異常
      如果一個異常沒有被處理,那麽,對於一個非圖形界面的程序而言,該程序會被中止並輸出異常信息;對於一個圖形界面程序,也會輸出異常的信息,但是程序並不中止,而是返回用錯誤頁面。
      語法:try、catch和finally(略),控制器模塊必須緊接在try塊後面。若擲出一個異常,異常控制機制會搜尋參數與異常類型相符的第一個控制器隨後它會進入那個catch 從句,並認為異常已得到控制。一旦catch 從句結束對控制器的搜索也會停止。
      捕獲多個異常(註意語法與捕獲的順序)(略)
      finally的用法與異常處理流程(略)
      異常處理做什麽?對於Java來說,由於有了垃圾收集,所以異常處理並不需要回收內存。但是依然有一些資源需要程序員來收集,比如文件、網絡連接和圖片等資源。
      應該聲明方法拋出異常還是在方法中捕獲異常?原則:捕捉並處理哪些知道如何處理的異常,而傳遞哪些不知道如何處理的異常。
      再次拋出異常
      ①為什麽要再次拋出異常? 在本級中,只能處理一部分內容,有些處理需要在更高一級的環境中完成,所以應該再次拋出異常。這樣可以使每級的異常處理器處理它能夠處理的異常。
      ②異常處理流程 :對應與同一try塊的catch塊將被忽略,拋出的異常將進入更高的一級。
      4 關於異常的其他問題
      ① 過度使用異常 :首先,使用異常很方便,所以程序員一般不再願意編寫處理錯誤的代碼,而僅僅是簡簡單單的拋出一個異常。這樣做是不對的,對於完全已知的錯誤,應該編寫處理這種錯誤的代碼,增加程序的魯棒性。另外,異常機制的效率很差。
      ② 將異常與普通錯誤區分開:對於普通的完全一致的錯誤,應該編寫處理這種錯誤的代碼,增加程序的魯棒性。只有外部的不能確定和預知的運行時錯誤才需要使用異常。
      ③ 異常對象中包含的信息 :一般情況下,異常對象唯一有用的信息就是類型信息。但使用異常帶字符串的構造函數時,這個字符串還可以作為額外的信息。調用異常對象的getMessage()、toString()或者printStackTrace()方法可以分別得到異常對象的額外信息、類名和調用堆棧的信息。並且後一種包含的信息是前一種的超集。

      總結:Throwable是所有Java程序中錯誤處理的父類,有兩種資類:Error和Exception。
      Error:表示由JVM所偵測到的無法預期的錯誤,由於這是屬於JVM層次的嚴重錯誤,導致JVM無法繼續執行,因此,這是不可捕捉到的,無法采取任何恢復的操作,頂多只能顯示錯誤信息。

      Exception:表示可恢復的例外,這是可捕捉到的。
      Java提供了兩類主要的異常:runtime exception和checked exception。checked 異常也就是我們經常遇到的IO異常,以及SQL異常都是這種異常。對於這種異常,JAVA編譯器強制要求我們必需對出現的這些異常進行catch。所以,面對這種異常不管我們是否願意,只能自己去寫一大堆catch塊去處理可能的異常。

      但是另外一種異常:runtime exception,也稱運行時異常,我們可以不處理。當出現這樣的異常時,總是由虛擬機接管。比如:我們從來沒有人去處理過NullPointerException異常,它就是運行時異常,並且這種異常還是最常見的異常之一。

      出現運行時異常後,系統會把異常一直往上層拋,一直遇到處理代碼。如果沒有處理塊,到最上層,如果是多線程就由Thread.run()拋出,如果是單線程就被main()拋出。拋出之後,如果是線程,這個線程也就退出了。如果是主程序拋出的異常,那麽這整個程序也就退出了。運行時異常是Exception的子類,也有一般異常的特點,是可以被Catch塊處理的。只不過往往我們不對他處理罷了。也就是說,你如果不對運行時異常進行處理,那麽出現運行時異常之後,要麽是線程中止,要麽是主程序終止。

      如果不想終止,則必須撲捉所有的運行時異常,決不讓這個處理線程退出。隊列裏面出現異常數據了,正常的處理應該是把異常數據舍棄,然後記錄日誌。不應該由於異常數據而影響下面對正常數據的處理。在這個場景這樣處理可能是一個比較好的應用,但並不代表在所有的場景你都應該如此。如果在其它場景,遇到了一些錯誤,如果退出程序比較好,這時你就可以不太理會運行時異常,或者是通過對異常的處理顯式的控制程序退出。

      異常處理的目標之一就是為了把程序從異常中恢復出來。
      二,常見的幾種RuntimeException如下: NullPointerException - 空指針引用異常
      ClassCastException - 類型強制轉換異常。
      IllegalArgumentException - 傳遞非法參數異常。
      ArithmeticException - 算術運算異常
      ArrayStoreException - 向數組中存放與聲明類型不兼容對象異常
      IndexOutOfBoundsException - 下標越界異常
      NegativeArraySizeException - 創建一個大小為負數的數組錯誤異常
      NumberFormatException - 數字格式異常
      SecurityException - 安全異常
      UnsupportedOperationException - 不支持的操作異常

      算術異常類:ArithmeticExecption
      空指針異常類:NullPointerException
      類型強制轉換異常:ClassCastException
      數組負下標異常:NegativeArrayException
      數組下標越界異常:ArrayIndexOutOfBoundsException
      違背安全原則異常:SecturityException
      文件已結束異常:EOFException
      文件未找到異常:FileNotFoundException
      字符串轉換為數字異常:NumberFormatException
      操作數據庫異常:SQLException
      輸入輸出異常:IOException
      方法未找到異常:NoSuchMethodException

      java.lang.AbstractMethodError
      抽象方法錯誤。當應用試圖調用抽象方法時拋出。

      java.lang.AssertionError
      斷言錯。用來指示一個斷言失敗的情況。

      java.lang.ClassCircularityError
      類循環依賴錯誤。在初始化一個類時,若檢測到類之間循環依賴則拋出該異常。

      java.lang.ClassFormatError
      類格式錯誤。當Java虛擬機試圖從一個文件中讀取Java類,而檢測到該文件的內容不符合類的有效格式時拋出。

      java.lang.Error
      錯誤。是所有錯誤的基類,用於標識嚴重的程序運行問題。這些問題通常描述一些不應被應用程序捕獲的反常情況。

      java.lang.ExceptionInInitializerError
      初始化程序錯誤。當執行一個類的靜態初始化程序的過程中,發生了異常時拋出。靜態初始化程序是指直接包含於類中的static語句段。

      java.lang.IllegalAccessError
      違法訪問錯誤。當一個應用試圖訪問、修改某個類的域(Field)或者調用其方法,但是又違反域或方法的可見性聲明,則拋出該異常。

      java.lang.IncompatibleClassChangeError
      不兼容的類變化錯誤。當正在執行的方法所依賴的類定義發生了不兼容的改變時,拋出該異常。一般在修改了應用中的某些類的聲明定義而沒有對整個應用重新編譯而直接運行的情況下,容易引發該錯誤。

      java.lang.InstantiationError
      實例化錯誤。當一個應用試圖通過Java的new操作符構造一個抽象類或者接口時拋出該異常.

      java.lang.InternalError
      內部錯誤。用於指示Java虛擬機發生了內部錯誤。

      java.lang.LinkageError
      鏈接錯誤。該錯誤及其所有子類指示某個類依賴於另外一些類,在該類編譯之後,被依賴的類改變了其類定義而沒有重新編譯所有的類,進而引發錯誤的情況。

      java.lang.NoClassDefFoundError
      未找到類定義錯誤。當Java虛擬機或者類裝載器試圖實例化某個類,而找不到該類的定義時拋出該錯誤。

      java.lang.NoSuchFieldError
      域不存在錯誤。當應用試圖訪問或者修改某類的某個域,而該類的定義中沒有該域的定義時拋出該錯誤。

      java.lang.NoSuchMethodError
      方法不存在錯誤。當應用試圖調用某類的某個方法,而該類的定義中沒有該方法的定義時拋出該錯誤。

      java.lang.OutOfMemoryError
      內存不足錯誤。當可用內存不足以讓Java虛擬機分配給一個對象時拋出該錯誤。

      java.lang.StackOverflowError
      堆棧溢出錯誤。當一個應用遞歸調用的層次太深而導致堆棧溢出時拋出該錯誤。

      java.lang.ThreadDeath
      線程結束。當調用Thread類的stop方法時拋出該錯誤,用於指示線程結束。

      java.lang.UnknownError
      未知錯誤。用於指示Java虛擬機發生了未知嚴重錯誤的情況。

      java.lang.UnsatisfiedLinkError
      未滿足的鏈接錯誤。當Java虛擬機未找到某個類的聲明為native方法的本機語言定義時拋出。

      java.lang.UnsupportedClassVersionError
      不支持的類版本錯誤。當Java虛擬機試圖從讀取某個類文件,但是發現該文件的主、次版本號不被當前Java虛擬機支持的時候,拋出該錯誤。

      java.lang.VerifyError
      驗證錯誤。當驗證器檢測到某個類文件中存在內部不兼容或者安全問題時拋出該錯誤。

      java.lang.VirtualMachineError
      虛擬機錯誤。用於指示虛擬機被破壞或者繼續執行操作所需的資源不足的情況。

      java.lang.ArithmeticException
      算術條件異常。譬如:整數除零等。

      java.lang.ArrayIndexOutOfBoundsException
      數組索引越界異常。當對數組的索引值為負數或大於等於數組大小時拋出。

      java.lang.ArrayStoreException
      數組存儲異常。當向數組中存放非數組聲明類型對象時拋出。

      java.lang.ClassCastException
      類造型異常。假設有類A和B(A不是B的父類或子類),O是A的實例,那麽當強制將O構造為類B的實例時拋出該異常。該異常經常被稱為強制類型轉換異常。

      java.lang.ClassNotFoundException
      找不到類異常。當應用試圖根據字符串形式的類名構造類,而在遍歷CLASSPAH之後找不到對應名稱的class文件時,拋出該異常。

      java.lang.CloneNotSupportedException
      不支持克隆異常。當沒有實現Cloneable接口或者不支持克隆方法時,調用其clone()方法則拋出該異常。

      java.lang.EnumConstantNotPresentException
      枚舉常量不存在異常。當應用試圖通過名稱和枚舉類型訪問一個枚舉對象,但該枚舉對象並不包含常量時,拋出該異常。

      java.lang.Exception
      根異常。用以描述應用程序希望捕獲的情況。

      java.lang.IllegalAccessException
      違法的訪問異常。當應用試圖通過反射方式創建某個類的實例、訪問該類屬性、調用該類方法,而當時又無法訪問類的、屬性的、方法的或構造方法的定義時拋出該異常。

      java.lang.IllegalMonitorStateException
      違法的監控狀態異常。當某個線程試圖等待一個自己並不擁有的對象(O)的監控器或者通知其他線程等待該對象(O)的監控器時,拋出該異常。

      java.lang.IllegalStateException
      違法的狀態異常。當在Java環境和應用尚未處於某個方法的合法調用狀態,而調用了該方法時,拋出該異常。

      java.lang.IllegalThreadStateException
      違法的線程狀態異常。當縣城尚未處於某個方法的合法調用狀態,而調用了該方法時,拋出異常。

      java.lang.IndexOutOfBoundsException
      索引越界異常。當訪問某個序列的索引值小於0或大於等於序列大小時,拋出該異常。

      java.lang.InstantiationException
      實例化異常。當試圖通過newInstance()方法創建某個類的實例,而該類是一個抽象類或接口時,拋出該異常。

      java.lang.InterruptedException
      被中止異常。當某個線程處於長時間的等待、休眠或其他暫停狀態,而此時其他的線程通過Thread的interrupt方法終止該線程時拋出該異常。

      java.lang.NegativeArraySizeException
      數組大小為負值異常。當使用負數大小值創建數組時拋出該異常。

      java.lang.NoSuchFieldException
      屬性不存在異常。當訪問某個類的不存在的屬性時拋出該異常。

      java.lang.NoSuchMethodException
      方法不存在異常。當訪問某個類的不存在的方法時拋出該異常。

      java.lang.NullPointerException
      空指針異常。當應用試圖在要求使用對象的地方使用了null時,拋出該異常。譬如:調用null對象的實例方法、訪問null對象的屬性、計算null對象的長度、使用throw語句拋出null等等。

      java.lang.NumberFormatException
      數字格式異常。當試圖將一個String轉換為指定的數字類型,而該字符串確不滿足數字類型要求的格式時,拋出該異常。

      java.lang.RuntimeException
      運行時異常。是所有Java虛擬機正常操作期間可以被拋出的異常的父類。

      java.lang.SecurityException
      安全異常。由安全管理器拋出,用於指示違反安全情況的異常。

      java.lang.StringIndexOutOfBoundsException
      字符串索引越界異常。當使用索引值訪問某個字符串中的字符,而該索引值小於0或大於等於序列大小時,拋出該異常。

      java.lang.TypeNotPresentException
      類型不存在異常。當應用試圖以某個類型名稱的字符串表達方式訪問該類型,但是根據給定的名稱又找不到該類型是拋出該異常。該異常與ClassNotFoundException的區別在於該異常是unchecked(不被檢查)異常,而ClassNotFoundException是checked(被檢查)異常。

      java.lang.UnsupportedOperationException
      不支持的方法異常。指明請求的方法不被支持情況的異常。

幾種常見的Runtime Exception