------- android培訓、java培訓、期待與您交流! ----------
異常
就是程序運行過程中,遇到了問題,這就叫異常。1,異常的體系
Throwable
其實應該分三種
Error
通常出現重大問題如:服務器宕機數據庫崩潰等。不編寫針對代碼對其處理。
Exception
除了 RuntimeException 和其所有子類,其他所有的異常類都是在編譯的時候必須要處理的,要麼try,要麼拋
RuntimeException
RuntimeException 和其所有的子類,都不會在編譯的時候報異常,而是在運行時報異常,這時候我們就需要回頭看看我們的代碼是否有問題,比如角標越界,空指針等
2,jvm是如何處理異常的
jvm發現運算是已經違反了數學運算規則,java將這種常見的問題進行描述,並封裝成了對象叫做ArithmeticException
當除0運算髮生後,jvm將該問題打包成了一個異常對象.
並將對象拋給調用者main函數,new ArithmeticException("/by zero");
main函數收到這個問題時,有兩種處理方式:
1,自己將該問題處理,然後繼續運行
2,自己沒有針對的處理方式,只有交給調用main的jvm來處理
jvm有一個默認的異常處理機制,就將該異常進行處理.並將該異常的名稱,異常的信息.異常出現的位置打印在了控制檯上
同時將程序停止運行
那麼jvm裏都封裝了哪些對異常的處理呢
3,處理異常處理方式
A:try...catch
格式:
try {
需要檢測的代碼;
}
catch(異常類 變量) {//異常類名 對象名= new 異常類名();
異常處理代碼;
}
世界上最真情的相依,就是你在try,我在catch,無論你發神馬脾氣,我都默默接受,靜靜處理
public class Demo1_Exception {
public static void main(String[] args) {
Demo d = new Demo(); //創建對象
try {
int num = d.div(10, 0); //調用div方法並將10和0給方法的參數
System.out.println(num); //打印調用方法的結果
} catch (Exception e) { //當try檢測出異常的時候,就跳到catch語句中
//接收異常Exception e = new ArithmeticException("/ by zero");
System.out.println(e); //打印異常對象的toString方法
System.out.println(e.toString());
System.out.println("錯了,除數爲零了"); //提示
}
System.out.println("11111111111111111111"); //異常處理完代碼可以繼續執行
}
}
class Demo {
public int div(int a,int b) { //a = 10,b = 0
return a / b; // new ArithmeticException("/ by zero");
}
}
try...catch(...)...finally
說一下final,finalize,finally的區別
1,final可以修飾類,可以修飾方法,可以修飾變量
2,finalize,在對象沒有更多引用,垃圾回收的時候調用
3,finally 關閉流,數據庫等,釋放資源
public class Test1 {
/**
* @param args
* finally的面試題
*/
public static void main(String[] args) {
Test t = new Test(); //創建對象
int num = t.getNum(); //調用getNum()方法
System.out.println(num);
}
}
class Test {
public int getNum() {
int x = 10;
try {
System.out.println(1/0); //執行1/0會出現異常,創建new ArithmetiException(\ by zero);對象
return x; //return語句
} catch (Exception e) {
x = 20; //將x值改爲20
return x; //return語句
} finally {
x = 30; //將x值改爲30
System.out.println("finally執行了嗎"); //輸出語句
//return x; finally中不要寫return語句
}
}
/*
* 當程序執行到try語句的時候,1/0違背了數學的運算規則出現異常,創建出new ArithmetiException(\ by zero)對象,程序跳轉到catch語句中
* 當程序跳轉到catch語句中,又將x值改爲了20,遇到return語句,return語句會建立一個返回路徑,將x裏面的20相當於裝到一個箱子裏,準備返回,在返回之前
* 看有沒有finally語句,如果有執行finally語句,但是雖然將x的值改爲了30,也不會影響到返回路徑中的值,所以最後的返回還是20
*/
}
可以有下面三種搭配形式
try...catch(...)
try...catch(...)...finally
try...finally 是不能進行異常處理的,必須拋出
B:拋出 throws throw
throws:用於標識函數暴露出的異常。thorws用在函數上,後面跟異常類名(可以由多個,隔開)。
throw:用於拋出異常對象。throw用在函數內,後面跟異常對象。new Exception();
public class Demo3_Throws {
/**
* @param args
* @throws Exception
* try catch和throws的區別
* 如果後續代碼想要繼續執行,只能try
* 如果後續代碼不想繼續執行,只能throws
*
* Exception 和RuntimeException的區別
* RutimeException是運行時異常,需要程序員回來修改自己的代碼
* Exception是編譯時異常,遇到編譯時異常,必須處理,要麼try,要麼throws(未雨綢繆異常)
*/
public static void main(String[] args) throws Exception {
Person p = new Person();
p.setAge(-17);
System.out.println(p.getAge());
System.out.println("222222222222222222222");
}
}
class Person {
private int age;
public Person() { //alt + shift + s + c 生成空參數的構造函數
super();
}
public Person(int age) { //alt + shift + s + o 根據字段生成有參數的構造函數
super();
this.age = age;
}
public int getAge() { //alt + shift + s + r 生成set和get方法
return age;
}
public void setAge(int age) throws Exception {
if(age > 0 && age < 200) {
this.age = age;
}else {
/*Exception e = new Exception("年齡非法");
throw e;*/
throw new Exception("年齡非法"); //用異常處理
//System.out.println("年齡非法"); //以前是這樣處理的
}
/*
* throw和throws的區別
* throw寫在方法內,後面跟的是異常對象
* throws寫在方法上,後面跟的是異常類名
*/
}
@Override
public String toString() { //alt + shift + s + s 生成toString方法
return "Person [age=" + age + "]";
}
}
C:到底用誰?
你能處理,建議處理。try...catch...finally
你處理不了,拋出。
在實際開發中,是分層開發,底層代碼是能拋出儘量拋出,用日誌記錄住異常信息,並提供解決方案
4,異常體系常見方法
A:getMessage() :返回此 throwable 的詳細消息字符串。
class Throwable {
String detailMessage;
Throwable(){}
Throwable(String message) {
this.detailMessage = message;
}
public String getMessage() {
return detailMessage;
}
}
B:toString():獲取異常類名和異常信息,返回字符串。
C:printStackTrace():獲取異常類名和異常信息,以及異常出現在程序中的位置。返回值void。
5,自定義異常
自定義類繼承Exception或者其子類(RuntimeException)
class MyException extends Exception{
MyException(){}
MyException(String message){
super(message); //將信息傳遞給父類,調用父類封裝好的構造方法
}
}
class Student {
public void giveAge(int age) throws MyException {
if(age>40 || age<16) {
//throw new MyExcetpion("建議不學了");
MyExcepiont my = new MyExcetpion("建議不學了");
throw my;
}
else {
System.out.println("可以學習Java");
}
}
}
E:RuntimeException和Exception
區別:RuntimeException就是要你改代碼的。你可以不處理。
6,異常總結
RuntimeException以及其子類如果在函數中被throw拋出,可以不用在函數上聲明。
子類覆蓋父類方法時,子類的方法必須拋出相同的異常或父類異常的子類。(父親壞了,兒子不能比父親更壞)
如果父類拋出了多個異常,子類覆蓋父類時,只能拋出相同的異常或者是他的子集,子類不能拋出父類沒有的異常
如果被覆蓋的方法沒有異常拋出,那麼子類的方法絕對不可以拋出異常,如果子類方法內有異常發生,那麼子類只能try,不能throws
當try對應多個catch時,最頂層的異常要放在最下面,反過來分析如果最頂層的異常放在第一行,那根據多態原理,後面的catch就沒用了,一般面試的時候會這麼問,開發的時候不會拋有繼承關係的異常