異常的概述
異常就是Java程式在運作過程中出現的錯誤。
異常的分類
通過API檢視Throwable
1.Error
伺服器當機,資料庫崩潰等
2.Exception
異常的繼承體系
* Throwable
* Error
* Exception
* RuntimeException運作時異常,我們最容易犯的錯誤
JVM預設是如何處理異常的
main函數收到這個問題時,有兩種處理方式:
a:自己将該問題處理,然後繼續運作
b:自己沒有針對的處理方式,隻有交給調用main的jvm來處理
* jvm有一個預設的異常處理機制,就将該異常進行處理.
* 并将該異常的名稱,異常的資訊.異常出現的位置列印在了控制台上,同時将程式停止運作
測試異常處理
public static void main(String[] args) {
// TODO Auto-generated method stub
int x = 10 / 0;
System.out.println(x);
//Exception in thread "main" java.lang.ArithmeticException: / by zero
}
public class ArithmeticExceptionextends RuntimeException
當出現異常的運算條件時,抛出此異常。例如,一個整數“除以零”時,抛出此類的一個執行個體。
異常處理的兩種方式
try…catch…finally
try catch
try catch finally
try finally
throws
try...catch處理異常的基本格式
try…catch…finally
try:用來檢測異常的
catch:用來捕獲異常的
finally:釋放資源
當通過trycatch将問題處理了,程式會繼續執行
public static void main(String[] args) {
try{
int x = 10/0;
System.out.println(x);
}catch(ArithmeticException e) {
//ArithmeticException a = new ArithmeticException();
System.out.println("出錯了,除數為零了");
System.out.println(e);//java.lang.ArithmeticException: / by zero
}
}
try...catch的方式處理多個異常
JDK7以後處理多個異常的方式及注意事項
安卓,用戶端開發,如何處理異常?try{}catch(Exception e){}
ee,服務端開發,一般都是底層開發,從底層向上抛
try後面如果跟多個catch,那麼小的異常放前面,大的異常放後面,根據多态的原理,如果大的放前面,就會将所有的子類對象接收
後面的catch就沒有意義了
public static void main(String[] args) {
int a = 10;
int b = 0;
int[] arr = {11,22,33,44,55};
try {
System.out.println(a / b);
System.out.println(arr[10]);
arr = null;
System.out.println(arr[0]);
} catch (ArithmeticException e) {
System.out.println("除數不能為零");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("索引越界了");
} catch (Exception e) { //Exception e = new NullPointerException();
System.out.println("出錯了");
}
System.out.println("over");
int a1 = 10;
int b1= 0;
int[] arr1 = {11,22,33,44,55};
//JDK7如何處理多個異常
try {
System.out.println(a1 / b1);
System.out.println(arr1[10]);
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("出錯了");
}
}
編譯期異常和運作期異常的差別
* Java中的異常被分為兩大類:編譯時異常和運作時異常。
* 所有的RuntimeException類及其子類的執行個體被稱為運作時異常,其他的異常就是編譯時異常
* 編譯時異常
* Java程式必須顯示處理,否則程式就會發生錯誤,無法通過編譯
* 運作時異常
* 無需顯示處理,也可以和編譯時異常一樣處理
Throwable的幾個常見方法
getMessage()
* 擷取異常資訊,傳回字元串。
:toString()
* 擷取異常類名和異常資訊,傳回字元串。
printStackTrace()
* 擷取異常類名和異常資訊,以及異常出現在程式中的位置。傳回值void。
public static void main(String[] args) {
try {
System.out.println(1/0);
} catch (Exception e) {
//Exception e = new ArithmeticException("/ by zero");
System.out.println(e.getMessage()); //擷取異常資訊/ by zero
System.out.println(e); //調用toString方法,列印異常類名和異常資訊
//java.lang.ArithmeticException: / by zero
e.printStackTrace();//jvm預設就用這種方式處理異常
//java.lang.ArithmeticException: / by zero
//at a.main(a.java:112)
}
}
throws的方式處理異常
*定義功能方法時,需要把出現的問題暴露出來讓調用者去處理。
那麼就通過throws在方法上辨別。
案例示範
* 舉例分别示範編譯時異常和運作時異常的抛出
* 編譯時異常的抛出必須對其進行處理
* 運作時異常的抛出可以處理也可以不處理
@throws Exception
public class a {
public static void main(String[] args) throws Exception {
Person p = new Person();
p.setAge(-17);
System.out.println(p.getAge());
}
}
class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
/*public void setAge(int age) throws Exception {
if(age >0 && age <= 150) {
this.age = age;
}else {
//Exception e = new Exception("年齡非法");
//throw e;
throw new Exception("年齡非法");
}
}*/
public void setAge(int age) {
if(age >0 && age <= 150) {
this.age = age;
}else {
throw new RuntimeException("年齡非法");
}
}
}
throw的概述以及和throws的差別
throw的概述
在功能方法内部出現某種情況,程式不能繼續運作,需要進行跳轉時,就用throw把異常對象抛出。
throws和throw的差別
:throws
* 用在方法聲明後面,跟的是異常類名
* 可以跟多個異常類名,用逗号隔開
* 表示抛出異常,由該方法的調用者來處理
throw
* 用在方法體内,跟的是異常對象名
* 隻能抛出一個異常對象名
* 表示抛出異常,由方法體内的語句處理
finally的特點及作用
特點
被finally控制的語句體一定會執行
特殊情況:在執行到finally之前jvm退出了(比如System.exit(0))
作用
用于釋放資源,在IO流操作和資料庫操作中會見到
return語句在執行之前看一看有沒有finally,如果有就将finally執行後在徹底傳回
public class b {
public static void main(String[] args) {
try {
System.out.println(10/0);
} catch (Exception e) {
System.out.println("除數為零了");
//System.exit(0);//退出jvm虛拟機
return;
} finally {
System.out.println("看看我執行了嗎");
}
}
}
finally關鍵字的面試題
面試題1 final,finally和finalize的差別
final可以修飾類,不能被繼承
final可以修飾方法,不能被重寫
final可以修飾變量,隻能指派一次
finally是try語句中的一個語句體,不能單獨使用,用來釋放資源
finalize是一個方法,當垃圾回收器确定不存在對該對象的更多引用時,由對象的垃圾回收器調用此方法。
protected void finalize() throws Throwable
當垃圾回收器确定不存在對該對象的更多引用時,由對象的垃圾回收器調用此方法。
子類重寫 finalize 方法,以配置系統資源或執行其他清除。
面試題2 如果catch裡面有return語句,請問finally的代碼還會執行嗎?如果會,請問是在return前還是return後。
先建立好傳回路徑,然後執行finally的代碼,最後徹底傳回
public class c {
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo d = new Demo();
System.out.println(d.method());//30
}
}
class Demo {
//@SuppressWarnings("finally")
public int method() {
int x = 10;
try {
x = 20;
System.out.println(1/0);
//return x;
return x;
} catch (Exception e) {
x = 30;
return x;
} finally {
x = 40;//catch已經建立好傳回路徑,在此改變x的值不會影響catch的傳回值
//return x;//40
//千萬不要在finally裡面寫傳回語句,因為finally的作用是為了釋放資源,是肯定會執行的
//如果在這裡面寫傳回語句,那麼try和catch的結果都會被改變,是以這麼寫就是犯罪
}
}
}
自定義異常概述和基本使用
為什麼需要自定義異常
易于排錯,望名生義(取決于名字)
自定義異常概述
繼承自Exception
繼承自RuntimeException
重寫異常的空參有參構造,參數向上傳遞super
自定義異常的基本使用
public class a {
public static void main(String[] args) throws Exception {
Person p = new Person();
p.setAge(-17);
System.out.println(p.getAge());
}
}
/*
* 自定義異常
* 也可以繼承 RuntimeException運作時異常,編譯時不用處理
* */
class AgeOutOfBoundsException extends Exception {
public AgeOutOfBoundsException() {
super();
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
//異常抛出處理,檢視Exception
public void setAge(int age) throws AgeOutOfBoundsException {
if(age >0 && age <= 150) {
this.age = age;
}else {
// throw new AgeOutOfBoundsException();
throw new AgeOutOfBoundsException("年齡錯誤");
}
}
}
異常的注意事項及如何使用異常處理
異常注意事項
a:子類重寫父類方法時,子類的方法必須抛出相同的異常或父類異常的子類。
b:如果父類抛出了多個異常,子類重寫父類時,隻能抛出相同的異常或者是他的子集,子類不能抛出父類沒有的異常
c:如果被重寫的方法沒有異常抛出,那麼子類的方法絕對不可以抛出異常,
如果子類方法内有異常發生,那麼子類隻能try,不能throws
如何使用異常處理
原則:如果該功能内部可以将問題處理,用try,如果處理不了,交由調用者處理,這是用throws
差別:
後續程式需要繼續運作就try
後續程式不需要繼續運作就throws
如果JDK沒有提供對應的異常,需要自定義異常。