在異常初識中只是簡單的介紹了異常的體系和異常的解決方法,這篇文章將對異常的一些特殊情況進行介紹。
1.自己定義一個異常類進行聲明或者捕獲
當我們不瞭解異常的種類或者異常中沒有我們想要的類那麼可以自己定義一個異常類,但是這個異常類要根據是編譯時異常還是運行時異常去繼承不同的異常類,當然可以直接繼承最終的異常類或是包括最大的異常類。一般而言都是運行時異常,而運行時異常要繼承的類爲RuntimeException類。
public class Main1 {
public static void main(String[] args) {
byte[] b;
try{
b=new byte[Integer.MAX_VALUE]; //這裏會產生異常,原因是數組的空間也有限制,Integer.MAX_VALUE這個值超過了數組的空間
}catch(OutOfMemoryError e){ //這是異常體系中存在的異常類,也是數組空間過大產生的異常,在這裏捕獲
System.out.println("數組解決了!"); //一旦捕獲到這個異常就解決
b=new byte[10];
}
System.out.println(b.length);
try{
test(121);
}catch(TimeBigerExcetion e){ //這是自己定義的異常類(該類在下面)
System.out.println(e+" 該問題已處理!"); //當我們在運行時捕獲到TimeBigerExcetion這個異常時,打印這個異常的信息,然後解決這個問題
}catch(TimeSmallerException e){ //當我們在運行時捕獲到TimeSmallerException 這個異常時,打印這個異常的信息,然後解決這個問題
System.out.println(e+" 都已交卷,問題已處理!");
}
System.out.println("over");
}
public static void test(int time) throws TimeBigerExcetion,TimeSmallerException { //這是上面試着運行的方法,我們發現可以拋出多個異常
if(time<0){ //當傳進來的參數也就是時間小於0,會產生TimeSmallerException這個異常,我們聲明它的對象,並給出信息
throw new TimeSmallerException("時間小於0,不能交卷!");
}
if(time>120){ //當傳進來的參數也就是時間大於正常時間,會產生TimeBigerExcetion這個異常,我們聲明它的對象,並給出信息
throw new TimeBigerExcetion("時間到了,停止作答");
}
}
}
class TimeSmallerException extends RuntimeException{ //這是自己定義的一個異常類,它繼承了RuntimeException類
public TimeSmallerException(String s){ //代參的構造方法,上面聲明時創建的對象就是調用的該構造方法
super(s);調用父類的構造方法,將打印信息傳給父類的構造方法
}
}
class TimeBigerExcetion extends Exception{//這也是自己定義的一個異常類,它繼承了Exception類
public TimeBigerExcetion(String s){
super(s);
}
}
2.父類聲明異常和子類聲明異常之間的關係
在繼承體系中,如果父類函數沒有聲明異常(編譯時),則子類重寫的函數也不可以聲明異常(編譯時);如果父類函數聲明異常,則子類重寫的函數可以聲明父類異常的子類或子集。
import java.io.FileNotFoundException;
public class Main {
public static void main(String[] args) {
Zi zi=new Zi();
// zi.show();
zi.test();
}
}
class Fu{ //父類
public void show(){ //父類的show方法沒有聲明異常
System.out.println("Fu show...");
}
public void test() throws MuException,FuException{ //父類的test方法聲明瞭兩個異常
System.out.println("Fu test...");
}
}
class Zi extends Fu{ //子類繼承父類
/*public void show() throws MuException { //這裏子類重寫了父類的show方法並聲明瞭異常
//然而這裏會編譯報錯的原因是
//Exception MuException is not compatible with throws clause in Fu.show()
//異常MuException與父類中的show方法的throw子句不兼容,
//意思就是父類在這個方法上都沒有聲明異常,你子類聲明幹啥?還不兼容。
//所以父類的方法沒有聲明異常,子類重寫的方法也不能聲明異常
System.out.println("Zi show...");
}*/
@Override
public void test(){ //子類重寫父類的test方法,沒有聲明異常,編譯沒有報錯。
//原因是子類繼承了父類,重寫了父類的方法,父類如果聲明瞭異常
//子類重寫的這個方法可以聲明它的子類或者子集,下面有兩個子類BoyException,GirlException,
//此方法在這裏可以聲明,或者也可以聲明MuException或者FuException,或者都可以聲明。
System.out.println("Zi test...");
}
}
class MuException extends Exception{
}
class FuException extends Exception{
}
class BoyException extends FuException{
}
class GirlException extends MuException{
}
3.finally語句塊
前面介紹到,想要處理一個異常可以選擇用try—catch的方法,但如果在try—catch中也出現了錯誤或者異常,還是會影響到程序的運行,在這裏可以使用finally語句塊,在此語句塊中的代碼,不論異常的是否發生,都會被執行。如下:
public class Main3 {
public static void main(String[] args) {
int[] a=new int[5];
try{
System.out.println(10/0); //這三句代碼都會出現異常
System.out.println(a[10]);
System.out.println("over1");
}catch(Exception e){ //進行捕獲處理
throw e; //捕獲到這個異常後還是向上聲明
}finally{ //finally語句塊後面的代碼仍會執行
System.out.println("finally...");
}
System.out.println("over2");
}
}
通過結果發現,雖然try-catch只捕獲到了一個異常,並且向上聲明,後面兩句有問題的代碼語句並沒有捕獲到,雖然程序是因異常而停止,但是在finally語句塊裏面的代碼仍正常執行。
final finally finalize的區別區別
final修飾的變量表示變量所存儲的地址不可更改
final修飾的函數表示該函數不能被重寫
final修飾的類表示該類不能被繼承
finally是異常處理語句中的一員,表示無論異常是否發生都會執行的語句
finalize() 當對象被回收時,由GC去調用該對象的這個函數,處理運行完的對象
public class Main {
public static void main(String[] args) {
Person p=new Person(1);
p=new Person(2);
p=new Person(3);
p=new Person(4);
p=new Person(5);
p=new Person(6);
p=new Person(7);
System.gc();
p=new Person(8);
p=new Person(9);
p=new Person(10);
}
}
class Person{
int age;
public Person(int age){
this.age=age;
}
@Override
protected void finalize() throws Throwable { //重寫finalize()函數
System.out.println("拜拜!"+age);
}
}
結果不唯一,因爲這是內部調用的,在外部重寫並調用意義不大。
總結:異常體系中最終父類是Throwable:但凡是一個問題產生,這個問題肯定要拋出
異常肯定是從函數內部產生的,從函數內向外拋出一個問題
Error:是由JVM直接拋出的嚴重性問題
Exception:是指一般性的問題
RuntimeException:運行時異常,只有在程序執行時才發生的異常
Exception及其子類:編譯時異常,在編譯的時候就可以檢測出來可能會發生異常
如何處理編譯時異常?
捕獲異常:try-catch
聲明異常:throws
什麼時候捕獲?—— 如果函數內部能夠解決這個問題則捕獲
什麼時候聲明?—— 函數內部解決不了,就要向調用者提示且聲明。如果拋出的異常一直被聲明直到JVM都沒人解決,那麼直接報錯
運行時異常可不可以被捕獲或聲明?—— 可以,但是必要,看具體需求
在捕獲異常時,沒有必要將大段的代碼放入try語句中?—— 只需要將可能出現問題的代碼放入即可,否則會導致一些和異常不相關的代碼被跳過
如果不想針對性的處理異常時,可以捕獲Exception即可,Throwable也可以,但是範圍太大,Error就根本不需要捕獲,下面用一個例子來說明何時捕獲何時聲明:
/*
* 張老師用電腦上課
* 電腦 藍屏
* 電腦 冒煙
* 課程 繼續/停止
* */
public class Main4 {
public static void main(String[] args) {
Teacher t=new Teacher("張"); //老師對象
try {
t.classBegin(); //先開始上課,打開電腦
} catch (ClassStopException e) { //如果這裏捕獲到了課程無法繼續的異常
//說明電腦冒煙了,老師無法解決,課程只能停止進行,進行自習或者放學等操作
System.out.println(e.toString());
System.out.println("下課!自習!放學!....");
}
}
}
class Teacher{ //老師類
String name; //老師有其姓名的稱呼
Computer com; //每個老師會有一個電腦
public Teacher(String name){
this.name=name;
this.com=new Computer();
}
public void classBegin() throws ClassStopException{
//開始上課,可能會因爲電腦的問題而導致課程無法進行,所以一旦出現突發狀況,課程會停止,首先聲明一個課程停止的異常
try {
com.start(); //先將電腦打開,試着講課
} catch (BlueScreenException e) { //在講課的過程中電腦可能會出現藍屏的狀況
System.err.println(e.getMessage()); //打印出錯的異常信息
com.restart(); //出現藍屏,人爲可以解決,進行電腦的重啓
}catch (MaoYanException e) { //也可能出現冒煙的情況
System.out.println(e.toString());
//電腦冒煙而導致的問題異常並不是冒煙異常,而是因爲電腦冒煙,人爲無法處理而導致了課程無法繼續進行的異常
//異常轉換 就是由一個問題從而引發出的另一個問題(上層所關注)
throw new ClassStopException("課程無法繼續....");
//所以一旦電腦出現冒煙問題,老師無法解決,這裏不能try—catch進行捕獲處理,只能向上聲明讓別人來處理
}
System.out.println(name+"老師上課..."); //如果沒有任何問題,那麼課程繼續
}
}
class Computer{ //電腦類
int state=2; //狀態標誌
public void start() throws BlueScreenException, MaoYanException{ //電腦開機可能出現異常
System.out.println("電腦開機...");
if(state==1){ //如果狀態標誌發生變化,相應的電腦狀態出現
//電腦出現問題並不是電腦自己重啓或者自己修理好的,而是它出現問題反饋給使用者,
//讓使用者去解決相應的問題,所有這裏一旦出現狀況應該是聲明
throw new BlueScreenException("電腦藍屏了....");
}else if(state==2){
throw new MaoYanException("冒煙了....");
}
}
public void restart(){ //重啓函數
System.out.println("電腦重啓...");
}
}
//藍屏異常
class BlueScreenException extends Exception{
public BlueScreenException(String info){
super(info);
}
}
//冒煙異常
class MaoYanException extends Exception{
public MaoYanException(String info){
super(info);
}
}
//課程無法繼續異常
class ClassStopException extends Exception{
public ClassStopException(String info){
super(info);
}
}