1:異常(理解)
(1)程序出現的不正常的情況。
(2)異常的體系
Throwable
|--Error嚴重問題,我們不處理。例如內存溢出
|--Exception
|--RuntimeException運行期異常,我們需要修正代碼
|--非RuntimeException 編譯期異常,必須處理的,否則程序編譯不通過
(3)異常的處理:
A:JVM的默認處理
把異常的名稱,原因,位置等信息輸出在控制檯,但是呢程序不能繼續執行了。
B:自己處理
a:try...catch...finally
自己編寫處理代碼,後面的程序可以繼續執行
* try...catch...finally的處理格式:
* try {
* 可能出現問題的代碼;
* }catch(異常名 變量) {
* 針對問題的處理;
* }finally {
* 釋放資源;
* }
*
* 變形格式:
* try {
* 可能出現問題的代碼;
* }catch(異常名 變量) {
* 針對問題的處理;
* }
*
* 注意:
* A:try裏面的代碼越少越好
* B:catch裏面必須有內容,哪怕是給出一個簡單的提示
public class ExceptionDemo {
public static void main(String[] args) {
// 第一階段
int a = 10;
// int b = 2;
int b = 0;
try {
System.out.println(a / b);
} catch (ArithmeticException ae) {
System.out.println("除數不能爲0");
}
// 第二階段
System.out.println("over");
}
}
* A:一個異常
* B:二個異常的處理
* a:每一個寫一個try...catch
* b:寫一個try,多個catch
* try{
* ...
* }catch(異常類名 變量名) {
* ...
* }
* catch(異常類名 變量名) {
* ...
* }
* ...
*
* 注意事項:
* 1:能明確的儘量明確,不要用大的來處理。
* 2:平級關係的異常誰前誰後無所謂,如果出現了子父關係,父必須在後面。
*
* 注意:
* 一旦try裏面出了問題,就會在這裏把問題給拋出去,然後和catch裏面的問題進行匹配,
* 一旦有匹配的,就執行catch裏面的處理,然後結束了try...catch
* 繼續執行後面的語句。
public class ExceptionDemo2 {
public static void main(String[] args) {
// method1();
// method2();
// method3();
method4();
}
public static void method4() {
int a = 10;
int b = 0;
int[] arr = { 1, 2, 3 };
// 爺爺在最後
try {
System.out.println(a / b);
System.out.println(arr[3]);
System.out.println("這裏出現了一個異常,你不太清楚是誰,該怎麼辦呢?");
} catch (ArithmeticException e) {
System.out.println("除數不能爲0");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("你訪問了不該的訪問的索引");
} catch (Exception e) {
System.out.println("出問題了");
}
// 爺爺在前面是不可以的
// try {
// System.out.println(a / b);
// System.out.println(arr[3]);
// System.out.println("這裏出現了一個異常,你不太清楚是誰,該怎麼辦呢?");
// } catch (Exception e) {
// System.out.println("出問題了");
// } catch (ArithmeticException e) {
// System.out.println("除數不能爲0");
// } catch (ArrayIndexOutOfBoundsException e) {
// System.out.println("你訪問了不該的訪問的索引");
// }
System.out.println("over");
}
// 兩個異常的處理
public static void method3() {
int a = 10;
int b = 0;
int[] arr = { 1, 2, 3 };
try {
System.out.println(arr[3]);
System.out.println(a / b);
// System.out.println(arr[3]);
} catch (ArithmeticException e) {
System.out.println("除數不能爲0");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("你訪問了不該的訪問的索引");
}
System.out.println("over");
}
// 兩個異常
public static void method2() {
int a = 10;
int b = 0;
try {
System.out.println(a / b);
} catch (ArithmeticException e) {
System.out.println("除數不能爲0");
}
int[] arr = { 1, 2, 3 };
try {
System.out.println(arr[3]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("你訪問了不該的訪問的索引");
}
System.out.println("over");
}
// 一個異常
public static void method1() {
// 第一階段
int a = 10;
// int b = 2;
int b = 0;
try {
System.out.println(a / b);
} catch (ArithmeticException ae) {
System.out.println("除數不能爲0");
}
// 第二階段
System.out.println("over");
}
}
處理多個異常問題:
/*
* JDK7出現了一個新的異常處理方案:
* try{
*
* }catch(異常名1 | 異常名2 | ... 變量 ) {
* ...
* }
*
* 注意:這個方法雖然簡潔,但是也不夠好。
* A:處理方式是一致的。(實際開發中,好多時候可能就是針對同類型的問題,給出同一個處理)
* B:多個異常間必須是平級關係。
*/
public class ExceptionDemo3 {
public static void main(String[] args) {
method();
}
public static void method() {
int a = 10;
int b = 0;
int[] arr = { 1, 2, 3 };
// try {
// System.out.println(a / b);
// System.out.println(arr[3]);
// System.out.println("這裏出現了一個異常,你不太清楚是誰,該怎麼辦呢?");
// } catch (ArithmeticException e) {
// System.out.println("除數不能爲0");
// } catch (ArrayIndexOutOfBoundsException e) {
// System.out.println("你訪問了不該的訪問的索引");
// } catch (Exception e) {
// System.out.println("出問題了");
// }
// JDK7的處理方案
try {
System.out.println(a / b);
System.out.println(arr[3]);
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("出問題了");
}
System.out.println("over");
}
}
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 在try裏面發現問題後,jvm會幫我們生成一個異常對象,然後把這個對象拋出,和catch裏面的類進行匹配。
* 如果該對象是某個類型的,就會執行該catch裏面的處理信息。
*
* 異常中要了解的幾個方法:
* public String getMessage():異常的消息字符串
* public String toString():返回異常的簡單信息描述
* 此對象的類的 name(全路徑名)
* ": "(冒號和一個空格)
* 調用此對象 getLocalizedMessage()方法的結果 (默認返回的是getMessage()的內容)
* printStackTrace() 獲取異常類名和異常信息,以及異常出現在程序中的位置。返回值void。把信息輸出在控制檯。
*/
public class ExceptionDemo {
public static void main(String[] args) {
String s = "2014-11-20";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date d = sdf.parse(s); // 創建了一個ParseException對象,然後拋出去,和catch裏面進行匹配
System.out.println(d);
} catch (ParseException e) { // ParseException e = new ParseException();
// ParseException
// e.printStackTrace();
// getMessage()
// System.out.println(e.getMessage());
// Unparseable date: "2014-11-20"
// toString()
// System.out.println(e.toString());
// java.text.ParseException: Unparseable date: "2014-11-20"
e.printStackTrace();
//跳轉到某個指定的頁面(index.html)
}
System.out.println("over");
}
}
b:throws
把自己處理不了的,在方法上聲明,告訴調用者,這裏有問題
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 有些時候,我們是可以對異常進行處理的,但是又有些時候,我們根本就沒有權限去處理某個異常。
* 或者說,我處理不了,我就不處理了。
* 爲了解決出錯問題,Java針對這種情況,就提供了另一種處理方案:拋出。
*
* 格式:
* throws 異常類名
* 注意:這個格式必須跟在方法的括號後面。
*
* 注意:
* 儘量不要在main方法上拋出異常。
* 但是我講課爲了方便我就這樣做了。
*
* 小結:
* 編譯期異常拋出,將來調用者必須處理。
* 運行期異常拋出,將來調用可以不用處理。
*/
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("今天天氣很好");
try {
method();
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("但是就是不該有霧霾");
method2();
}
// 運行期異常的拋出
public static void method2() throws ArithmeticException {
int a = 10;
int b = 0;
System.out.println(a / b);
}
// 編譯期異常的拋出
// 在方法聲明上拋出,是爲了告訴調用者,你注意了,我有問題。
public static void method() throws ParseException {
String s = "2014-11-20";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(s);
System.out.println(d);
}
}
(4)面試題
A:編譯期異常和運行期異常的區別?
編譯期異常 必須要處理的,否則編譯不通過
運行期異常 可以不處理,也可以處理
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 編譯時異常和運行時異常的區別
* 編譯期異常:Java程序必須顯示處理,否則程序就會發生錯誤,無法通過編譯
* 運行期異常:無需顯示處理,也可以和編譯時異常一樣處理
*/
public class ExceptionDemo {
public static void main(String[] args) {
// int a = 10;
// int b = 0;
// if (b != 0) {
// System.out.println(a / b);
// }
String s = "2014-11-20";
// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// Date d = sdf.parse(s);
try {
Date d = sdf.parse(s);
System.out.println(d);
} catch (ParseException e) {
// e.printStackTrace();
System.out.println("解析日期出問題了");
}
}
}
B:throw和throws是的區別
throw:
在方法體中,後面跟的是異常對象名,並且只能是一個
throw拋出的是一個異常對象,說明這裏肯定有一個異常產生了
throws:
在方法聲明上,後面跟的是異常的類名,可以是多個
throws是聲明方法有異常,是一種可能性,這個異常並不一定會產生
Demo:
/*
* throw:如果出現了異常情況,我們可以把該異常拋出,這個時候的拋出的應該是異常的對象。
*
* throws和throw的區別(面試題)
throws
用在方法聲明後面,跟的是異常類名
可以跟多個異常類名,用逗號隔開
表示拋出異常,由該方法的調用者來處理
throws表示出現異常的一種可能性,並不一定會發生這些異常
throw
用在方法體內,跟的是異常對象名
只能拋出一個異常對象名
表示拋出異常,由方法體內的語句處理
throw則是拋出了異常,執行throw則一定拋出了某種異常
*/
public class ExceptionDemo {
public static void main(String[] args) {
// method();
try {
method2();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void method() {
int a = 10;
int b = 0;
if (b == 0) {
throw new ArithmeticException();
} else {
System.out.println(a / b);
}
}
public static void method2() throws Exception {
int a = 10;
int b = 0;
if (b == 0) {
throw new Exception();
} else {
System.out.println(a / b);
}
}
}
(5)finally關鍵字及其面試題
A:finally用於釋放資源,它的代碼永遠會執行。特殊情況:在執行到finally之前jvm退出了
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* finally:被finally控制的語句體一定會執行
* 注意:如果在執行到finally之前jvm退出了,就不能執行了。
*
* A:格式
* try...catch...finally...
* B:用於釋放資源,在IO流操作和數據庫操作中會見到
*/
public class FinallyDemo {
public static void main(String[] args) {
String s = "2014-11-20";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = null;
try {
// System.out.println(10 / 0);
d = sdf.parse(s);
} catch (ParseException e) {
e.printStackTrace();
System.exit(0);
} finally {
System.out.println("這裏的代碼是可以執行的");
}
System.out.println(d);
}
}
B:面試題
a:final,finally,finalize的區別?
b:如果在catch裏面有return,請問finally還執行嗎?如果執行,在return前還是後
會,前。
C:異常處理的變形
try...catch...finally
try...catch...
try...catch...catch...
try...catch...catch...fianlly
try...finally
Demo:
/*
* 面試題:
* 1:final,finally和finalize的區別
* final:最終的意思,可以修飾類,成員變量,成員方法
* 修飾類,類不能被繼承
* 修飾變量,變量是常量
* 修飾方法,方法不能被重寫
* finally:是異常處理的一部分,用於釋放資源。
* 一般來說,代碼肯定會執行,特殊情況:在執行到finally之前jvm退出了
* finalize:是Object類的一個方法,用於垃圾回收
*
* 2:如果catch裏面有return語句,請問finally裏面的代碼還會執行嗎?
* 如果會,請問是在return前,還是return後。
* 會。前。
*
* 準確的說,應該是在中間。
*
* 3:try...catch...finally的格式變形
* A:try...catch...finally
* B:try...catch
* C:try...catch...catch...
* D:try...catch...catch...finally
* E:try...finally
* 這種做法的目前是爲了釋放資源。
*/
public class FinallyDemo2 {
public static void main(String[] args) {
System.out.println(getInt());
}
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;
}
}
(6)自定義異常
繼承自Exception或者RuntimeException,只需要提供無參構造和一個帶參構造即可
* java不可能對所有的情況都考慮到,所以,在實際的開發中,我們可能需要自己定義異常。
* 而我們自己隨意的寫一個類,是不能作爲異常類來看的,要想你的類是一個異常類,就必須繼承自Exception或者RuntimeException
*
* 兩種方式:
* A:繼承Exception
* B:繼承RuntimeException
MyException類:
package cn.itcast_08;
/*
* java不可能對所有的情況都考慮到,所以,在實際的開發中,我們可能需要自己定義異常。
* 而我們自己隨意的寫一個類,是不能作爲異常類來看的,要想你的類是一個異常類,就必須繼承自Exception或者RuntimeException
*
* 兩種方式:
* A:繼承Exception
* B:繼承RuntimeException
*/
public class MyException extends Exception {
public MyException() {
}
public MyException(String message) {
super(message);
}
}
Teacher類:
package cn.itcast_08;
public class Teacher {
public void check(int score) throws MyException {
if (score > 100 || score < 0) {
throw new MyException("分數必須在0-100之間");
} else {
System.out.println("分數沒有問題");
}
}
// 針對MyException繼承自RuntimeException
// public void check(int score) {
// if (score > 100 || score < 0) {
// throw new MyException();
// } else {
// System.out.println("分數沒有問題");
// }
// }
}
Student類:
package cn.itcast_08;
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();
}
}
}
(7)異常的注意實現
A:父的方法有異常拋出,子的重寫方法在拋出異常的時候必須要小於等於父的異常
B:父的方法沒有異常拋出,子的重寫方法不能有異常拋出
C:父的方法拋出多個異常,子的重寫方法必須比父少或者小
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 異常注意事項:
* A:子類重寫父類方法時,子類的方法必須拋出相同的異常或父類異常的子類。(父親壞了,兒子不能比父親更壞)
* B:如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異常或者是他的子集,子類不能拋出父類沒有的異常
* C:如果被重寫的方法沒有異常拋出,那麼子類的方法絕對不可以拋出異常,如果子類方法內有異常發生,那麼子類只能try,不能throws
*/
public class ExceptionDemo {
}
class Fu {
public void show() throws Exception {
}
public void method() {
}
}
class Zi extends Fu {
@Override
public void show() throws ArithmeticException {
}
@Override
public void method() {
// String s = "2014-11-20";
// SimpleDateFormat sdf = new SimpleDateFormat();
// Date d = sdf.parse(s);
// System.out.println(d);
}
}