Java異常之try,catch,finally,throw,throws
你能區分異常和錯誤嗎?
我們每天上班,正常情況下可能30分鐘就能到達。但是由於車多,人多,道路擁擠,致使我們要花費更多地時間,這就是生活中的異常!
程式和生活一樣都會出現異常,先來看個異常:
上面出現的是算數錯誤的異常。
在java中,除去一些編譯上的錯誤(語法)之外,就有異常和錯誤!
異常的定義是可自己進行處理後,程式依然可以正常執行下去!錯誤是Java虛擬機器丟擲的,終止程式的執行,這就是程式和異常的區別。
一:什麼是異常處理?
異常處理機制就像我們對平時可能遇到的意外情況,預先想好了一些處理的辦法。也就是說,在程式執行程式碼的時候,萬一發生了異常,程式會按照預定的處理辦法對異常進行處理,異常處理完畢後,程式繼續執行。
java的異常處理是通過5個關鍵字來實現的:try、catch、finally、throw、throws。
二:java異常類的層次結構
三.常見的異常型別
Exception 異常層次結構的根類
ArithmeticException 算數錯誤情形
ArrayIndexOutOfBoundsException 陣列下標越界
NullPointerException 嘗試訪問null物件成員
ClassNotFoundException 不能載入所需的類
InputMismatchException 欲得到的資料型別與實際輸入的型別不匹配
IllegalArgumentException 方法接受到非法引數
ClassCastException 物件強制型別轉換出錯
NumberFormatException 數字格式轉換異常
四.具體例項
- try—catch
package Test;
import java.util.Scanner;
public class Test_Test {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
System.out.println("請輸入被除數:");
try {
int num1=input.nextInt();
System.out.println("請輸入除數:" );
int num2=input.nextInt();
System.out.println(String.format("%d / %d = %d",
num1, num2, num1 / num2));
}catch (Exception e) {
System.err.println("出現錯誤:被除數和除數必須是整數,"+
"除數不能為零。");
System.out.println(e.getMessage());
}
}
執行結果如下:
System.err.println();這種輸出方式可以輸出錯誤的訊息,在控制檯呈現紅色。
System.out用於正常的輸出,也就是程式真正想輸出的內容。而System.err用於出錯資訊的輸出,也就是你本來不期待看到的東西。
System.out.println(e.getMessage());
這行的作用是——返回該錯誤的詳細資訊的字串。
- try-catch-finally
package Test;
import java.util.Scanner;
public class Test_Test {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
System.out.println("請輸入被除數:");
try {
int num1=input.nextInt();
System.out.println("請輸入除數:");
int num2=input.nextInt();
System.out.println(String.format("%d / %d = %d",
num1, num2, num1 / num2));
}catch (Exception e) {
System.err.println("出現錯誤:被除數和除數必須是整數,"+
"除數不能為零。");
System.out.println(e.getMessage());
}
finally{
System.out.println("Thanks");
}
}
}
執行結果如下:
try-catch-finally 程式塊的流程大致分為兩種情況:
1. 如果try塊中所有語句正常執行完畢,那麼finally塊就會被執行。
2. 如果try語句在執行過程中碰到異常,無論這種異常能否被catch塊捕獲到,都將執行finally塊中的程式碼。
try-catch-finally結構中try塊是必須有的,catch和finally塊為可選,但兩者至少必須出現其中之一。
- try—catch-catch-finally(多重catch塊)
package Test;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test_Test {
public static void main(String[] args) {
Scanner input =new Scanner(System.in);
System.out.println("請輸入被除數:");
try {
int num1=input.nextInt();
System.out.println("請輸入除數:");
int num2=input.nextInt();
System.out.println(String.format("%d / %d = %d",
num1, num2, num1 / num2));
}catch (InputMismatchException e) {
System.err.println("被除數和除數必須是整數。");
}
catch (ArithmeticException e) {
System.err.println("除數不能為零。");
}
catch (Exception e) {
System.err.println("其他未知異常。");
System.out.println(e.getMessage());
}
finally{
System.out.println("Thanks");
}
}
}
執行結果如下:
所以,在寫異常處理的時候,一定要把異常範圍小的放在前面,範圍大的放在後面,Exception這個異常的根類一定要剛在最後一個catch裡面,如果放在前面或者中間,任何異常都會和Exception匹配的,就會報已捕獲到…異常的錯誤。
下面是try-catch-finally中包含return的情況:
- 情況一:try{} catch(){}finally{} return;
正常按程式順序執行即可。
package Test;
public class Test_Test {
public static void main(String[] args) {
Test1();
}
public static int Test1(){
int x = 1;
try
{
x++;
System.out.println("我有用!");
}
catch (Exception e) {
System.out.println("我沒用!");
}
finally
{
++x;
System.out.println("我也有用!");
}
return 2;
}
}
執行結果如下:
- 情況2:try{ return; }catch(){} finally{} return;
程式執行try塊中return之前(包括return語句中的表示式運算)程式碼; 再執行finally塊,最後執行try中return; finally塊之後的語句return,因為程式在try中已經return所以不再執行。
package Test;
public class Test_Test {
public static void main(String[] args) {
Test1();
}
public static int Test1(){
int x = 1;
try
{
x++;
System.out.println("我有用!");
return 6;
}
catch (Exception e) {
System.out.println("我沒用!");
}
finally
{
++x;
System.out.println("我也有用!");
}
return 2;
}
}
執行結果如下:
- 情況3:try{} catch(){return;} finally{} return;
程式先執行try,如果遇到異常執行catch塊, 有異常:則執行catch中return之前(包括return語句中的表示式運算)程式碼,再執行finally語句中全部程式碼, 最後執行catch塊中return. finally之後也就是4處的程式碼不再執行。 無異常:執行完try再finally再return.
1.有異常的情況:
package Test;
public class Test_Test {
public static void main(String[] args) {
Test1();
}
public static int Test1(){
int x = 5;
try
{
int num=x / 0;
System.out.println(num);
}
catch (ArithmeticException e) {
System.err.println("除數不能為0!");
return 6;
}
finally
{
++x;
System.out.println("finally");
}
return 2;
}
}
執行結果如下:
2.無異常的情況:
package Test;
public class Test_Test {
public static void main(String[] args) {
Test1();
}
public static int Test1(){
int x = 5;
try
{
System.out.println("try");
}
catch (ArithmeticException e) {
System.err.println("除數不能為0!");
return 6;
}
finally
{
++x;
System.out.println("finally");
}
return 2;
}
}
執行結果如下:
- 情況4:try{ return; }catch(){} finally{return;}
程式執行try塊中return之前(包括return語句中的表示式運算)程式碼; 再執行finally塊,因為finally塊中有return所以提前退出。
package Test;
public class Test_Test {
public static void main(String[] args) {
Test1();
}
public static int Test1(){
int x = 5;
try
{
int num = x / 0;
System.out.println("try");
return 3;
}
catch (ArithmeticException e) {
System.err.println("除數不能為0!");
}
finally
{
++x;
System.out.println("finally");
return 2;
}
}
}
執行結果如下:
- 情況5:try{} catch(){return;}finally{return;}
程式執行catch塊中return之前(包括return語句中的表示式運算)程式碼; 再執行finally塊,因為finally塊中有return所以提前退出。
package Test;
public class Test_Test {
public static void main(String[] args) {
Test1();
}
public static int Test1(){
int x = 5;
try
{
int num = x / 0;
System.out.println("try");
}
catch (ArithmeticException e) {
System.err.println("除數不能為0!");
return 4;
}
finally
{
++x;
System.out.println("finally");
return 2;
}
}
}
執行結果如下:
情況6:try{ return;}catch(){return;} finally{return;}
程式執行try塊中return之前(包括return語句中的表示式運算)程式碼; 有異常:執行catch塊中return之前(包括return語句中的表示式運算)程式碼; 則再執行finally塊,因為finally塊中有return所以提前退出。 無異常:則再執行finally塊,因為finally塊中有return所以提前退出。
1.有異常
package Test;
public class Test_Test {
public static void main(String[] args) {
Test1();
}
public static int Test1(){
int x = 5;
try
{
int num = x / 0;
System.out.println("try");
return 4;
}
catch (ArithmeticException e) {
System.err.println("除數不能為0!");
return 4;
}
finally
{
++x;
System.out.println("finally");
return 2;
}
}
}
執行結果如下:
2.無異常
package Test;
/**
* Java學習交流QQ群:589809992 我們一起學Java!
*/
public class Test_Test {
public static void main(String[] args) {
Test1();
}
public static int Test1(){
int x = 5;
try
{
// int num = x / 0;
// System.out.println("try");
return 4;
}
catch (ArithmeticException e) {
System.err.println("除數不能為0!");
return 4;
}
finally
{
++x;
System.out.println("finally");
return 2;
}
}
}
執行結果如下:
最終結論:
任何執行try 或者catch中的return語句之前,都會先執行finally語句,如果finally存在的話。
如果finally中有return語句,那麼程式就return了,所以finally中的return是一定會被return的。
編譯器把finally中的return實現為一個warning。
- throw——丟擲異常
丟擲異常有三種形式,一是throw,一個throws,還有一種系統自動拋異常。
系統丟擲異常:
package Test;
public class Test2 {
public static void main(String[] args) {
int a = 5, b =0;
System.out.println(5/b);
}
}
執行結果如下:
throw丟擲異常:
throw是語句丟擲一個異常。語法:throw (異常物件);
package Test;
/**
* Java學習交流QQ群:589809992 我們一起學Java!
*/
public class Test2 {
public static void main(String[] args) {
String s = "abc";
if(s.equals("abc")) {
throw new NumberFormatException();
} else {
System.out.println(s);
}
}
}
執行結果如下:
- throws——宣告異常
throws是方法可能丟擲異常的宣告。(用在宣告方法時,表示該方法可能要丟擲異常)語法:(修飾符)(方法名)([引數列表])[throws(異常類)]{……}
package Test;
public class Test2 {
public static void main(String[] args) {
try {
Test3();
} catch (NumberFormatException e) {
System.err.println("非資料型別不能轉換。");
}
}
public static void Test3() throws NumberFormatException{
String s = "abc";
System.out.println(Double.parseDouble(s));
}
}
執行結果如下:
如果在一個方法體中丟擲了異常,那麼我們就可以通過throws——宣告異常來通知呼叫者,非常方便。
throws表示出現異常的一種可能性,並不一定會發生這些異常;throw則是丟擲了異常,執行throw則一定丟擲了某種異常物件。
最後說一句,try-catch-finally雖好用,但是如果是濫用,這樣只是會讓程式的可讀性變的很糟糕,當程式報錯,就無法快速準確的定位了,物盡其用 人盡其才嘛!