1、什么是異常?
首先,讓我們來看看下圖的例子:
在這個例子中,存在的錯誤碼由除以0的結果。由于除以0而導致異常: ArithmeticException
HelloException.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package com.yiibai.tutorial.exception; public class HelloException { public static void main(String[] args) { System.out.println( "Three" ); // This division no problem. int value = 10 / 2 ; System.out.println( "Two" ); // This division no problem. value = 10 / 1 ; System.out.println( "One" ); // This division has problem, divided by 0. // An error has occurred here. value = 10 / 0 ; // And the following code will not be executed. System.out.println( "Let's go!" ); } } |
運行這個例子,得到的結果是:
可以看到控制臺屏幕上的通知。錯誤通知是很清楚的,包括代碼行的信息。
讓我們通過下圖中的流程看看下面的程序:
- 程序從(1),(2)至(5)步驟正常運行。
- 在步驟(6)程序除以0。
- 程序跳轉出 main 方法后,而(7)代碼行還沒有被執行。
我們將修改上述實施例的代碼。
HelloCatchException.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
package com.yiibai.tutorial.exception; public class HelloCatchException { public static void main(String[] args) { System.out.println( "Three" ); // This division no problem. int value = 10 / 2 ; System.out.println( "Two" ); // This division no problem. value = 10 / 1 ; System.out.println( "One" ); try { // This division has problem, divided by 0. // An error has occurred here. value = 10 / 0 ; // And the following code will not be executed. System.out.println( "Value =" + value); } catch (ArithmeticException e) { // The code in the catch block will be executed System.out.println( "Error: " + e.getMessage()); // The code in the catch block will be executed System.out.println( "Ignore..." ); } // This code is executed System.out.println( "Let's go!" ); } } |
運行示例結果:
Three
Two
One
Error: / by zero
Ignore...
Let's go!
我們將按以下實例圖像的流程來解釋下面的程序。
- 步驟(1)至(5)是完全正常的。
- 異常發生在步驟(6),除以0出現了問題。
- 它立即跳到catch塊執行命令,步驟(7)被跳過。
- 步驟(8),(9)被執行。
- 步驟(10)被執行。
2、 異常層次結構
這是Java異常的分層圖的模型。
最高的類是:Throwable
兩個直接子類是 Error 和 Exception。
在異常轉移有一個RuntimeException子類,包括Java中的編譯時未檢查異常。檢查并取消檢查在編譯時,在下一部分的實施示例中說明。
注意:您的類應該從兩個分支:Error或Exception繼承,而不是直接從Throwable繼承。
當一個動態鏈接失敗,或在虛擬機的一些其他的“硬”故障發生時,虛擬機引發這個錯誤。典型的Java程序不捕獲錯誤,所以Java程序都不會拋出任何錯誤。大多數程序拋出并捕獲從Exception類派生的對象。異常指示出現了一個問題,但是這些問題并不是嚴重系統性問題。你寫的大多數程序將會拋出和捕獲異常。
Exception類在Java包定義了許多子類。這些子類指明不同類型的可能會發生異常。 例如,NegativeArraySizeException表明程序試圖創建一個大小為負的數組。
一個導演的子類在Java語言中的特殊含義: RuntimeException類表示Java虛擬機中發生(在運行期間)的異常。運行時異常的一個例子是NullYiibaierException異常,其中,當一種方法試圖通過一個空引用來訪問對象的成員時就會引發。 NullYiibaierException 可以在任何地方出現某個程序試圖取消引用一個對象的引用。經常檢查異常捕獲的好處遠遠超過它的成本。
由于運行時異常是無所不在的,在試圖捕獲或指定所有的時間是徒勞的作法(不可讀和不可維護的代碼), 編譯器允許運行時異常去未捕獲和指定。
Java包定義幾個RuntimeException類。您可以捕獲這些異常,就像其他異常。但是并不需要一種方法來指定它拋出運行時異常。此外可以創建自己的RuntimeException子類。 運行時異常 - 下面討論包含何時以及如何使用運行時異常進行了深入探討。 3、使用try-catch處理異常
編寫從Exception 繼承的類。
AgeException.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package com.yiibai.tutorial.exception.basic; public class AgeException extends Exception { public AgeException(String message) { super (message); } } TooYoungException.java package com.yiibai.tutorial.exception.basic; public class TooYoungException extends AgeException { public TooYoungException(String message) { super (message); } } |
TooOldException.java
1
2
3
4
5
6
7
8
9
|
package com.yiibai.tutorial.exception.basic; public class TooOldException extends AgeException { public TooOldException(String message) { super (message); } } |
以及AgeUtils類檢查年齡的檢查靜態方法。
AgeUtils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.yiibai.tutorial.exception.basic; public class AgeUtils { // This method checks the age. // If age is less than 18, the method will throw an exception TooYoungException // If age greater than 40, the method will throw an exception TooOldException public static void checkAge( int age) throws TooYoungException, TooOldException { if (age < 18 ) { // If age is less than 18, an exception will be thrown // This method ends here. throw new TooYoungException( "Age " + age + " too young" ); } else if (age > 40 ) { // If age greater than 40, an exception will be thrown. // This method ends here. throw new TooOldException( "Age " + age + " too old" ); } // If age is between 18-40. // This code will be execute. System.out.println( "Age " + age + " OK!" ); } } |
檢查異常和未經檢查的異常:
AgeException是Exception,TooOldException的子類和TooYoungException2是 AgeException直接子類,所以它們是“Checked Exception”
在AgeUtils.checkAge(int)方法已經拋出異常,需要通過關鍵字“throws”,列出它們的方法聲明。或者可以聲明拋出更多的級別。
在使用 AgeUtils.checkAge(int) 位置也必須進行處理,以捕獲異常,或繼續拋出去。
"Checked exception" 是由 "Java Compiler"來檢查。
有兩個選擇:
TryCatchDemo1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package com.yiibai.tutorial.exception.basic; public class TryCatchDemo1 { public static void main(String[] args) { System.out.println( "Start Recruiting ..." ); // Check age System.out.println( "Check your Age" ); int age = 50 ; try { AgeUtils.checkAge(age); System.out.println( "You pass!" ); } catch (TooYoungException e) { // Do something here .. System.out.println( "You are too young, not pass!" ); System.out.println(e.getMessage()); } catch (TooOldException e) { // Do something here .. System.out.println( "You are too old, not pass!" ); System.out.println(e.getMessage()); } } } |
在下面的例子中,我們將通過父類捕獲異常(超Exception類)。
TryCatchDemo2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package com.yiibai.tutorial.exception.basic; public class TryCatchDemo2 { public static void main(String[] args) { System.out.println( "Start Recruiting ..." ); // Check age System.out.println( "Check your Age" ); int age = 15 ; try { // Here can throw TooOldException or TooYoungException AgeUtils.checkAge(age); System.out.println( "You pass!" ); } catch (AgeException e) { // If an exception occurs, type of AgeException // This catch block will be execute System.out.println( "Your age invalid, you not pass" ); System.out.println(e.getMessage()); } } } |
也可以組不同的異常在塊中來處理,如果它們對邏輯程序處理是相同的方式。
TryCatchDemo3.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
package com.yiibai.tutorial.exception.basic; public class TryCatchDemo3 { public static void main(String[] args) { System.out.println( "Start Recruiting ..." ); // Check age System.out.println( "Check your Age" ); int age = 15 ; try { // Here can throw TooOldException or TooYoungException AgeUtils.checkAge(age); System.out.println( "You pass!" ); } catch (TooYoungException | TooOldException e) { // Catch multi exceptions in one block. System.out.println( "Your age invalid, you not pass" ); System.out.println(e.getMessage()); } } } |
4、 try-catch-finally
我們已習慣于通過 try-catch 塊捕獲錯誤。Try-catch-finally 來完全處理異常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
try { // Do something here } catch (Exception1 e) { // Do something here } catch (Exception2 e) { // Do something here } finally { // Finally block is always executed // Do something here } |
TryCatchFinallyDemo.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
package com.yiibai.tutorial.exception.basic; public class TryCatchFinallyDemo { public static void main(String[] args) { String text = "001234A2" ; int value = toInteger(text); System.out.println( "Value= " + value); } public static int toInteger(String text) { try { System.out.println( "Begin parse text: " + text); // An Exception can throw here (NumberFormatException). int value = Integer.parseInt(text); return value; } catch (NumberFormatException e) { // In the case of 'text' is not a number. // This catch block will be executed. System.out.println( "Number format exception " + e.getMessage()); // Returns 0 if NumberFormatException occurs return 0 ; } finally { System.out.println( "End parse text: " + text); } } } |
這是程序的流程。 finally塊無論什么情況下總會被執行。
5、 環繞異常
- 我們需要一些類參與到這個例子:
- Person: 模擬一個受試者招募到公司的信息:姓名,年齡,性別。
- GenderException: 性別異常。
- ValidateException: 異常評估求職者。
- ValidateUtils: 靜態方法類綜合評價面試者。
- 如果男性年齡在18-40之間的被認為是有效的。
Person.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package com.yiibai.tutorial.exception.wrap; public class Person { public static final String MALE = "male" ; public static final String FEMALE = "female" ; private String name; private String gender; private int age; public Person(String name, String gender, int age) { this .name = name; this .gender = gender; this .age = age; } public String getName() { return name; } public void setName(String name) { this .name = name; } public String getGender() { return gender; } public void setGender(String gender) { this .gender = gender; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } } |
GenderException.java
1
2
3
4
5
6
7
8
9
|
package com.yiibai.tutorial.exception.wrap; // Gender Exception. public class GenderException extends Exception { public GenderException(String message) { super (message); } } |
ValidateException 類包有其他異常。
ValidateException.java
1
2
3
4
5
6
7
8
9
10
|
package com.yiibai.tutorial.exception.wrap; public class ValidateException extends Exception { // Wrap an Exception public ValidateException(Exception e) { super (e); } } |
ValidateUtils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package com.yiibai.tutorial.exception.wrap; import com.yiibai.tutorial.exception.basic.AgeUtils; public class ValidateUtils { public static void checkPerson(Person person) throws ValidateException { try { // Check age. // Valid if between 18-40 // This method can throw TooOldException, TooYoungException. AgeUtils.checkAge(person.getAge()); } catch (Exception e) { // If not valid // Wrap this exception by ValidateException, and throw throw new ValidateException(e); } // If that person is Female, ie invalid. if (person.getGender().equals(Person.FEMALE)) { GenderException e = new GenderException( "Do not accept women" ); throw new ValidateException(e); } } } |
WrapperExceptionDemo.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
package com.yiibai.tutorial.exception.wrap; public class WrapperExceptionDemo { public static void main(String[] args) { // One participant recruitment. Person person = new Person( "Marry" , Person.FEMALE, 20 ); try { // Exceptions may occur here. ValidateUtils.checkPerson(person); } catch (ValidateException wrap) { // Get the real cause. // May be TooYoungException, TooOldException, GenderException Exception cause = (Exception) wrap.getCause(); if (cause != null ) { System.out.println( "Not pass, cause: " + cause.getMessage()); } else { System.out.println(wrap.getMessage()); } } } } |
6、RuntimeException和子類 RuntimeException類及其子類都是“未檢查的例外”。它不是由Java編譯器在編譯時進行檢查。在某些情況下,你可以從這個分支繼承編寫自己的異常。
下面是屬于RuntimeException分支一些類(當然,這還不是全部)。
一些處理這種類型異常的例子:
6.1- NullYiibaierException
這是最常見的異常,通常會導致錯誤在程序中。異常被拋出,當你調用方法或訪問一個空對象的字段。
NullYiibaierExceptionDemo.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
package com.yiibai.tutorial.exception.runtime; public class NullYiibaierExceptionDemo { // For example, here is a method that can return null string. public static String getString() { if ( 1 == 2 ) { return "1==2 !!" ; } return null ; } public static void main(String[] args) { // This is an object that references not null. String text1 = "Hello exception" ; // Call the method retrieves the string length. int length = text1.length(); System.out.println( "Length text1 = " + length); // This is an object that references null. String text2 = getString(); // Call the method retrieves the string length. // NullYiibaierException will occur here. // It is an exception occurs at runtime (type of RuntimeException) // Javac compiler does not force you to use a try-catch block to handle it length = text2.length(); System.out.println( "Finish!" ); } } |
運行示例的結果:
在現實中,像處理其他異常時,可以使用 try-catch 來捕獲并處理這個異常。 然而,這是機械的,通常情況下,我們應該檢查,以確保在使用它之前,對象不為空值。
您可以更正上面的代碼,使其類似于下面的以避免空指針異常:
1
2
3
4
5
6
7
8
|
// This is a null object. String text2 = getString(); // Check to make sure 'Text2' are not null. // Instead of using try-catch. if (text2 != null ) { length = text2.length(); } |
6.2- ArrayIndexOfBoundException
當您試圖訪問一個無效的索引的數組元素就會發生此異常。例如,一個數組有10個元素可以訪問,但您訪問的是索引為20的元素。
ArrayIndexOfBoundsExceptionDemo.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.yiibai.tutorial.exception.runtime; public class ArrayIndexOfBoundsExceptionDemo { public static void main(String[] args) { String[] strs = new String[] { "One" , "Two" , "Three" }; // Access to the element has index 0. String str1 = strs[ 0 ]; System.out.println( "String at 0 = " + str1); // Access to the element has index 5. // ArrayIndexOfBoundsException occur here. String str2 = strs[ 5 ]; System.out.println( "String at 5 = " + str2); } } |
為了避免 ArrayIndexOfBoundsException,我們更多的應該是檢查數組而不是使用try-catch。
1
2
3
4
5
6
|
if (strs.length > 5 ) { String str2 = strs[ 5 ]; System.out.println( "String at 5 = " + str2); } else { System.out.println( "No elements with index 5" ); } |
以上就是本文的全部內容,希望對大家的學習有所幫助。