Java之異常處理,日期處理
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之異常處理,日期處理