Throwable
Error:嚴(yán)重問題,通常出現(xiàn)重大問題如:運行的類不存在或者內(nèi)存溢出术浪,服務(wù)器宕機瓢对,數(shù)據(jù)庫崩潰等等。出現(xiàn)了error胰苏,靠我們的異常處理方式 try{}catch(){}和throws是處理不了的硕蛹,必須找出哪個地方犯了這么嚴(yán)重的錯誤,然后修改代碼,改正確了之后法焰,程序才能夠運行起來僵腺,否則程序絕對運行不起來。
代碼演示:
public class Test {
public static void main(String[] args) {
show();
}
private static void show() {
show(); //java.lang.StackOverflowError棧內(nèi)存溢出壶栋,這種情況必須更改代碼
}
}
Exception
Exception下面RuntimeException下面的兒子都是運行期異常辰如。運行時期異常可以處理也可以不處理
1)不處理:如果不處理贵试,也不會報錯(eclipse報紅線)琉兜,java就會用jvm默認(rèn)的的處理方式,它就把異常的類型毙玻、原因豌蟋、位置直接顯示在了控制臺。并且退出當(dāng)前線程(可以理解為退出虛擬機)桑滩,同時后面的代碼是不能執(zhí)行的梧疲。
2)處理:為了讓后面的代碼繼續(xù)執(zhí)行,那么我們處理異常, 我們采用try{}catch(){}
try{
可能發(fā)生問題的代碼运准。
}catch(異常類名 變量名){
變量名.printStackTrace();//異常處理代碼幌氮。
}finally{
釋放資源代碼。(數(shù)據(jù)庫,IO)
}
代碼演示:
public static void main(String[] args) {
try{
System.out.println(10/0);
}catch(ArithmeticException a) { //ArithmeticException a = new ArithmeticException();
System.out.println("出錯了,除數(shù)為零了"); //打印出:出錯了,除數(shù)為零了
}
System.out.println("1111111111111111"); //打印出:1111111111111111胁澳,不會影響后面代碼的運行
}
注意事項:
①一個try里面有多個異常怎么辦该互?可以一個try后面跟多個catch,但是如果異常是平級關(guān)系韭畸,沒有順序問題宇智。如果異常存在著子父關(guān)系,父一定要放在最后胰丁。
代碼演示:
public static void demo1() {
int a = 10;
int b = 0;
int[] arr = {11,22,33,44,55};
try {
System.out.println(a / b); //運行時報錯
System.out.println(arr[10]); //此代碼不會執(zhí)行
arr = null; //此代碼不會執(zhí)行
System.out.println(arr[0]); //此代碼不會執(zhí)行
} catch (ArithmeticException e) {
System.out.println("除數(shù)不能為零");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("索引越界了");
} catch (Exception e) { //Exception是父類 父類一定放在最后面
System.out.println("出錯了");
}
System.out.println("over"); //不影響后面代碼的運行
}
②:可以用一個catch随橘, catch里面寫一個Exception就可以了
代碼演示:
public static void demo1() {
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 (Exception e) { //多態(tài)
System.out.println("出錯了");
}
System.out.println("over");
}
③了解JDK7的新特性。格式:try{}catch(異常1 | 異常2 | 異常3 ... 變量名){}
代碼演示:
public static void main(String[] args) {
int a = 10;
int b = 0;
int[] arr = {11,22,33,44,55};
//JDK7如何處理多個異常
try {
System.out.println(a / b);
System.out.println(arr[10]);
} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
System.out.println("出錯了");
}
}
④我們一直在處理異常的時候都是打印的一句話锦庸,雖然提示了我們有錯誤机蔗,但是沒有告訴開發(fā)人員是哪一行代碼出錯,沒有告訴開發(fā)人員是哪個異常酸员! 那這樣的話蜒车,不利于開發(fā)人員對代碼進行維護,所以我們就有了標(biāo)準(zhǔn)的異常catch代碼幔嗦,既能打印出異常消息酿愧,顯示出哪一行出的錯,又能不影響后面的代碼執(zhí)行邀泉。首先介紹:Throwable中的方法:
public String getMessage():返回的是異常的消息字符串嬉挡。
public String toString():返回異常的簡單描述信息钝鸽。全路徑類名 : 消息字符串
public void printStackTrace():把錯誤信息顯示在控制臺。
代碼演示:
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); //java.lang.ArithmeticException: / by zero
e.printStackTrace();
/*java.lang.ArithmeticException: / by zero at com.heima.exception.Demo5_Throwable.main(Demo5_Throwable.java:18)
*/
}
}
⑤finally的程序除了虛擬機掛掉庞钢,其他的時候都會執(zhí)行的拔恰,所以把一些必須要執(zhí)行的重要代碼放在finally里面執(zhí)行。比如釋放資源代碼基括。
⑥final颜懊,finally和finalize的區(qū)別:
final可以修飾類,不能被繼承风皿;修飾方法,不能被重寫河爹;修飾變量,只能賦值一次
finally是try語句中的一個語句體桐款,不能單獨使用咸这,用來釋放資源
finalize是一個方法,當(dāng)垃圾回收器確定不存在對該對象的更多引用時魔眨,由對象的垃圾回收器調(diào)用此方法
面試題
如果catch里面有return語句媳维,請問finally的代碼還會執(zhí)行嗎?如果會遏暴,請問是在return前還是return后侄刽。
?
public static void main(String[] args) {
System.out.println(method()); //30
}
public static int method() {
int x = 10;
try {
x = 20;
System.out.println(1/0);
return x;
} catch (Exception e) {
x = 30;
return x; //當(dāng)程序執(zhí)行到這兒,內(nèi)存中已經(jīng)生成了一條"return 30"的路徑拓挥,
//但是發(fā)現(xiàn)finally還沒有執(zhí)行呢唠梨,就又去執(zhí)行了finally里面的內(nèi)容讓x變成了40袋励,
//但是"return 30"的路徑已經(jīng)生成了侥啤,即使x變成了40也是沒用的!
//接著還是會繼續(xù)執(zhí)行"return 30" 然后結(jié)束方法茬故。
} finally {
x = 40;
}
}
⑦如果處理運行期異常盖灸,我們還可以采用Throws 聲明異常,但是我們一般不用(為什么磺芭?請看下面解釋)赁炎。編譯期異常:Exception下面非RuntimeException 的異常;運行期異常:RuntimeException下的異常钾腺。如果是運行期異常的話我們聲明和不聲明是一樣的徙垫。而且只要運行時出現(xiàn)異常的話,聲明和不聲明異常放棒,后面的代碼都不會再繼續(xù)執(zhí)行了姻报,那么我們?yōu)槭裁从袀€聲明異常這種處理方式呢?這就引出了編譯期異常间螟,編譯期異常就是在開發(fā)人員編寫代碼的時候吴旋,程序提示你這兒以后可能會出現(xiàn)一些常見的問題损肛,讓咱們在寫代碼的時候就要針對這常見的問題采取措施,不要等運行的時候出錯了再去解決荣瑟,因為這個問題很常見,可以預(yù)防,所以java呢為了這樣提示開發(fā)人員就讓開發(fā)人員在編寫的時候都不讓開發(fā)人員編譯通過躬贡,必須要采取措施氢妈,而開發(fā)人員采取的措施一個就是用try{}catch(){} ,另一個就是不用管這個異常啦嚷掠,直接拋給虛擬機(throws聲明一下)同波,這兩種方式都證明開發(fā)人員知道這兒可能會出現(xiàn)異常,并采取措施了叠国。 所以聲明異常是給編譯期異常準(zhǔn)備的未檩。 運行期異常雖然能用,但是沒啥實際意義粟焊,所以運行期異常我們一般還是用try{}catch(){}冤狡。
自定義異常
有時候需要我們自己定義一些異常,很簡單项棠,只需要建一個類(類名見名知意) 繼承這個異常體系(繼承Exception或者其兒子)悲雳,寫一個有參構(gòu)造方法用來傳入異常信息,遇到特定業(yè)務(wù)的時候throw就可以了香追。
代碼演示:
//建一個類(類名見名知意)繼承這個異常體系(繼承Exception或者其兒子)
class AgeOutOfBoundsException extends Exception {
public AgeOutOfBoundsException() {
super();
}
public AgeOutOfBoundsException(String message) {//寫一個有參構(gòu)造方法合瓢,用來傳入異常信息
super(message);
}
}
public class Demo_Exception {
public static void main(String[] args) throws Exception {//p.setAge(-17);main方法中調(diào)用setAge方法的時候,因為setAge方法體上聲明了一個編譯期異常 所以main方法的方法體上也要聲明該編譯期異常
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{
//方法體內(nèi)如果有 "throw 編譯期異常對象" 透典,則方法體上必須用throws聲明該編譯期異常
if(age >0 && age <= 150) {
this.age = age;
}else {
throw new AgeOutOfBoundsException("年齡非法"); //遇到特定業(yè)務(wù)的時候throw就可以了
}
}
}
throw和throws的區(qū)別:
throw 寫在方法里面晴楔,后面跟對象,只能跟一個對象
throws 寫在方法聲明上峭咒,后面跟異常類型税弃,可以跟多個異常類型并用逗號隔開
字符類關(guān)系中的異常
a:子類重寫父類方法時,子類的方法必須拋出相同的異炒斩樱或父類異常的子類则果。(父親壞了,兒子不能比父親更壞)
class Fu{
public void show() throws IOException{ //父類方法聲明 IOException
}
}
class Son extends Fu{
public void show() throws IOException{ //這樣是可以的 聲明和父類相同的IOException
}
public void show() throws FileNotFoundException{
//這樣是可以的,聲明父類異常的兒子漩氨,也就是IOException的子類FileNotFoundException
}
public void show() throws Exception{
//這樣是不行的 聲明父類異常的父類西壮,也就是IOException的父類Exception
}
}
b:如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異辰芯或者是他的子集款青,子類不能拋出父類沒有的異常。
class Fu{
public void show() throws IOException,NoSuchMethodException{
}
}
class Son extends Fu{
public void show() throws IOException{//這樣寫可以 子類只能拋出相同的異掣撤茫或者是他的子集
}
public void show() throws ParseException{//這樣做是不行的 子類不能拋出父類沒有的異常
}
}
c:如果被重寫的方法沒有異常拋出可都,那么子類的方法絕對不可以拋出異常缓待;如果子類方法內(nèi)有異常發(fā)生,那么子類只能try,不能throws
class Fu{
public void show(){
}
}
class Son extends Fu{
public void show(){//這樣做可以 如果被重寫的方法沒有異常拋出,那么子類的方法絕對不可以拋出異常
}
public void show() throws Exception{//這樣做 不可以
}
public void show() {
//如果被重寫的方法沒有異常拋出,而且子類方法內(nèi)有異常發(fā)生,那么子類只能try,不能throws
try {
FileInputStream fis = new FileInputStream("xxx.txt");
//new FileInputStream("xxx.txt");這句話有個編譯期異常
} catch(Exception e) {
e.printStackTrace();
}
}
}
好了今天就先說到這了渠牲,明天繼續(xù)旋炒。想了解更多學(xué)習(xí)知識签杈,請關(guān)注微信公眾號“阿Q說”瘫镇,獲取更多學(xué)習(xí)資料吧!你也可以后臺留言說出你的疑惑答姥,阿Q將會在后期的文章中為你解答铣除。每天學(xué)習(xí)一點點,每天進步一點點鹦付。