1. 程式人生 > >Java之異常處理,日期處理

Java之異常處理,日期處理

出了 指定 初始化 ring () next height 常見問題 自定義

Java異常處理

異常:異常就是Java程序在運行過程中出現的錯誤。

異常由來:問題也是現實生活中一個具體事務,也可以通過java 的類的形式進行描述,並封裝成對象。其實就是Java對不正常情況進行描述後的對象體現。

異常分類圖解:

技術分享

Throwable
  1--Error 嚴重問題,我們不處理。
  2--Exception
    (1)--RuntimeException 運行期異常,我們需要修正代碼
    (2)--非RuntimeException 編譯期異常,必須處理的,否則程序編譯不通過

Java虛擬機默認處理

public class ExceptionTest1 {
    
public static void main(String[] args) { int a=10; int b=0; System.out.println(a/b); System.out.println("通過!"); } }

技術分享

這是一個除數為0造成的典型的運行異常

這是Java虛擬機默認的處理,將異常的名稱,原因,出現的問題輸出在控制臺

同時也中斷程序

自己處理異常

try...catch...finally
  自己編寫處理代碼,後面的程序可以繼續執行
throws
  拋出,把自己處理不了的,在方法上聲明,告訴調用者,這裏有問題

註意:try裏面的代碼越少越好

將問題包在try中,程序可以運行,但是catch裏必須有代碼,不然只能是隱藏問題而不是處理異常

public class ExceptionTest1 {
    public static void main(String[] args) {
        int a=10;
        int b=0;
        try{
            System.out.println(a/b);
        }catch(ArithmeticException Ex){
            System.out.println(
"異常!除數不能為0"); } System.out.println("通過!"); } }

技術分享

//多個異常的情況
public class ExceptionTest1 {
    public static void main(String[] args) {
        int a=10;
        int b=0;
        int i[]={0,1,2};
        try{
            System.out.println(i[3]);
            System.out.println(a/b);
        }catch(ArithmeticException Ex){
            System.out.println("異常!除數不能為0");
        }catch(ArrayIndexOutOfBoundsException Ex){
            System.out.println("異常!訪問無效!");
        }
        System.out.println("通過!");
    }
}

技術分享

我們可以看到並沒有輸出第一個catch中的異常處理語句,這是因為一旦try 裏出了問題就會把這個異常拋出去到 catch 中匹配異常,匹配到之後執行 catch 裏的語句,然後結束 try...catch 在執行下面的語句

public class ExceptionTest1 {
    public static void main(String[] args) {
        int a=10;
        int b=0;
        int i[]={0,1,2};
        try{
            System.out.println(i[3]);
            System.out.println(a/b);
            System.out.println("未知的異常!");
        }catch(ArithmeticException Ex){
            System.out.println("異常!除數不能為0");
        }catch(ArrayIndexOutOfBoundsException Ex){
            System.out.println("異常!訪問無效!");
        }catch(Exception Ex){//Exception可以匹配所有的異常類型
            System.out.println("異常!未知!");
        }
        System.out.println("通過!");
    }
}

在catch()中我們應該寫異常類型,能明確的盡量明確以節約資源,不能明確的也可以寫 Exception

註意:Exception 可以匹配所有異常,所有不能寫在前面,否則後面的無效,所以,平級關系的異常前後順序無所謂,父子關系的異常父類必須在後面。

try...catch...finally的格式變形
* A:try...catch...finally
* B:try...catch
* C:try...catch...catch...
* D:try...catch...catch...finally
* E:try...finally 這種做法的目前是為了釋放資源。

JDK7的新特性,可以再catch中將多個異常用 | 隔開

public class ExceptionTest1 {
    public static void main(String[] args) {
        int a=10;
        int b=0;
        int i[]={0,1,2};
        try{
            System.out.println(i[3]);
            System.out.println(a/b);
            System.out.println("未知的異常!");
        }catch(ArithmeticException | ArrayIndexOutOfBoundsException Ex){
            System.out.println("異常!");
        }
        System.out.println("通過!");
    }
}

這種方法的局限性,只能給出一個解決方案,多個異常要是平級關系

編譯期異常和運行期異常的區別?
  編譯期異常 必須要處理的,否則編譯不通過
  運行期異常 可以不處理,也可以處理

Throwable類的常見方法

getMessage

public String getMessage()
返回此 throwable 的詳細消息字符串。
返回:
Throwable 實例(可以為 null)的詳細消息字符串。

toString

public String toString()
返回此 throwable 的簡短描述。如果此 Throwable 對象是利用非空詳細消息字符串創建的,則結果是三個字符串的串聯:
  • 此對象的實際類的名稱
  • ": "(冒號和空格)
  • 此對象的 getMessage() 方法的結果
如果此 Throwable 對象利用 null 詳細消息字符串創建,則返回此對象的實際類的名稱。
覆蓋:
Object 中的 toString
返回:
該 throwable 的字符串表示形式。

printStackTrace

public void printStackTrace()
將此 throwable 及其追蹤輸出至標準錯誤流。此方法將此 Throwable 對象的堆棧跟蹤輸出至錯誤輸出流,作為字段 System.err 的值。輸出的第一行包含此對象的 toString() 方法的結果。剩余行表示以前由方法 fillInStackTrace() 記錄的數據。此信息的格式取決於實現,但以下示例是最常見的:
 java.lang.NullPointerException
         at MyClass.mash(MyClass.java:9)
         at MyClass.crunch(MyClass.java:6)
         at MyClass.main(MyClass.java:3)
 
本示例通過運行以下程序生成:
 class MyClass {
     public static void main(String[] args) {
         crunch(null);
     }
     static void crunch(int[] a) {
         mash(a);
     }
     static void mash(int[] b) {
         System.out.println(b[0]);
     }
 }
 
對於帶初始化非空 cause 的 throwable 的追蹤,通常應該包括 cause 的追蹤。此信息的格式取決於實現,但以下示例是最常見的:
 HighLevelException: MidLevelException: LowLevelException
         at Junk.a(Junk.java:13)
         at Junk.main(Junk.java:4)
 Caused by: MidLevelException: LowLevelException
         at Junk.c(Junk.java:23)
         at Junk.b(Junk.java:17)
         at Junk.a(Junk.java:11)
         ... 1 more
 Caused by: LowLevelException
         at Junk.e(Junk.java:30)
         at Junk.d(Junk.java:27)
         at Junk.c(Junk.java:21)
         ... 3 more
 
註意,存在包含字符 "..." 的行。這些行指示此異常的椎棧跟蹤的其余部分匹配來自異常(由 "enclosing" 異常引起)的堆棧跟蹤底部的指定數量的幀。這種簡便方法可以大大縮短通常情況下的輸出長度,這裏拋出了包裝的異常,其方法與捕獲“作為 cause 的異常”的方法相同。上述示例通過運行以下程序生成:
 public class Junk {
     public static void main(String args[]) { 
         try {
             a();
         } catch(HighLevelException e) {
             e.printStackTrace();
         }
     }
     static void a() throws HighLevelException {
         try {
             b();
         } catch(MidLevelException e) {
             throw new HighLevelException(e);
         }
     }
     static void b() throws MidLevelException {
         c();
     }   
     static void c() throws MidLevelException {
         try {
             d();
         } catch(LowLevelException e) {
             throw new MidLevelException(e);
         }
     }
     static void d() throws LowLevelException { 
        e();
     }
     static void e() throws LowLevelException {
         throw new LowLevelException();
     }
 }

 class HighLevelException extends Exception {
     HighLevelException(Throwable cause) { super(cause); }
 }

 class MidLevelException extends Exception {
     MidLevelException(Throwable cause)  { super(cause); }
 }
 
 class LowLevelException extends Exception {
 }
public class ExceptionTest1 {
    public static void main(String[] args) {
        int a=10;
        int b=0;
        int i[]={0,1,2};
        try{
            System.out.println(i[3]);
        }catch(Exception Ex){
            System.out.println(Ex.getMessage());  //異常的消息字符串
            System.out.println(Ex.toString());  //異常消息簡單描述
            Ex.printStackTrace();    //獲取異常類名和異常信息,以及異常出現在程序中的未知,void,把信息輸出在控制臺
        }
        System.out.println("通過!");
    }
}

throws

定義功能方法時,需要把出現的問題暴露出來讓調用者去處理。那麽就通過throws在方法上標識。

    public void show() throws ParseException  {
        String s="2017-07-23";
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d=sdf.parse(s);
        System.out.println(sdf.format(d));
    }
        try {
            d.show();
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

註意:編譯期異常拋出將來調用者必須處理

運行期異常拋出,將來調用者可以不處理

throws後也可以跟多個異常

throw

在功能方法內部出現某種情況,程序不能繼續運行,需要進行跳轉時,就用throw把異常對象拋出。這時拋出的應該是異常的對象。

        int a=10;
        int b=0;
        if(b==0){
            throw new ArithmeticException();
        }else{
            System.out.println(a/b);
        }

throws和throw的區別
throws
用在方法聲明後面,跟的是異常類名
可以跟多個異常類名,用逗號隔開
表示拋出異常,由該方法的調用者來處理
throws表示出現異常的一種可能性,並不一定會發生這些異常
throw
用在方法體內,跟的是異常對象名
只能拋出一個異常對象名
表示拋出異常,由方法體內的語句處理
throw則是拋出了異常,執行throw則一定拋出了某種異常

總結

如果該功能內部可以將問題處理,用try,如果處理不了,交由調用者處理,這是用throws
區別:
後續程序需要繼續運行就try
後續程序不需要繼續運行就throws
舉例:
感冒了就自己吃點藥就好了,try
吃了好幾天藥都沒好結果得了H7N9,那就的得throws到醫院
如果醫院沒有特效藥就變成Error了

finally

特點:

被finally控制的語句體一定會執行
特殊情況:在執行到finally之前jvm退出了(比如System.exit(0))

作用:用於釋放資源

        String s="2017-07-23";
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d=null;
        try{
            d=sdf.parse(s);
        }catch(ParseException ex){
            ex.printStackTrace();
        }finally{
            System.out.println("!這裏的語句一定會執行!");
        }
        System.out.println(d);    

常見問題:

final,finally和finalize的區別
final:最終的意思,可以修飾類,成員變量,成員方法
修飾類,類不能被繼承
修飾變量,變量是常量
修飾方法,方法不能被重寫
finally:是異常處理的一部分,用於釋放資源。
一般來說,代碼肯定會執行,特殊情況:在執行到finally之前jvm退出了
finalize:是Object類的一個方法,用於垃圾回收

如果catch裏面有return語句,finally裏面的代碼還會執行嗎?
如果會,是在return前,還是return後。
會。前。
準確的說,應該是在中間。

    public static int getInt() {
        int a = 10;
        try {
            System.out.println(a / 0);
            a = 20;
        } catch (ArithmeticException e) {
            a = 30;
            return a;
            /*
             * return a在程序執行到這一步的時候,這裏不是return a而是return 30;這個返回路徑就形成了。
             *它發現後面還有finally,所以繼續執行finally的內容,a=40
             * 再次回到以前的返回路徑,繼續走return 30;
             */
        } finally {
            a = 40;
            return a;//如果這樣結果就是40了。
        }
        return a; //這裏的語句不會執行

自定義異常

Java中定義了很多常見的異常類,但是在實際運行中也需要我們自己定義異常類。

自定義的異常類需要繼承自繼承自Exception或者RuntimeException,只需要提供無參構造和一個帶參構造即可

//自定義異常類
public class MyException extends Exception {
    public MyException() {
    }

    public MyException(String message) {
        super(message);
    }
}
//老師類
public class Teacher {
    public void check(int score) throws MyException {
        if (score > 100 || score < 0) {
            throw new MyException("分數必須在0-100之間");
        } else {
            System.out.println("分數沒有問題");
        }
    }
}
//主方法
import java.util.Scanner;
public class StudentDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入學生成績:");
        int score = sc.nextInt();

        Teacher t = new Teacher();
        try {
            t.check(score);
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}

技術分享

如果繼承自RuntimeException

public class Teacher {
    public void check(int score) throws MyException {
    //針對MyException繼承自RuntimeException
    public void check(int score) {
    if (score > 100 || score < 0) {
        throw new MyException();
    } else {
        System.out.println("分數沒有問題");
    }
    }
}
public class MyException extends RuntimeException {

}

異常的註意
A:父的方法有異常拋出,子的重寫方法在拋出異常的時候必須要小於等於父的異常
B:父的方法沒有異常拋出,子的重寫方法不能有異常拋出
C:父的方法拋出多個異常,子的重寫方法必須比父少或者小

Java之異常處理,日期處理