1. 程式人生 > 實用技巧 >建立自定義異常

建立自定義異常

Thinking in Java異常筆記

建立自定義異常

package exception;

class MyException extends Exception {
    public MyException() {}

    public MyException(String message) {
        super(message);
    }
}

public class FullConstructors {
    public static void f() throws MyException {
        System.out.println("Throwing My exception from f()");
        throw new MyException();
        }
    public static void g() throws MyException {
        System.out.println("Throwing My exception from g()");
        throw new MyException("Originated in g()");
    }

    public static void main(String[] args) {
        try {
            f();
        } catch (MyException e) {
            e.printStackTrace(System.out);
        }
        try {
            g();
        } catch (MyException e) {
            e.printStackTrace(System.out);
        }
    }
}
/* output
Throwing My exception from f()
exception.MyException
	at exception.FullConstructors.f(FullConstructors.java:14)
	at exception.FullConstructors.main(FullConstructors.java:23)
Throwing My exception from g()
exception.MyException: Originated in g()
	at exception.FullConstructors.g(FullConstructors.java:18)
	at exception.FullConstructors.main(FullConstructors.java:28)
*/

如果使用e.printStackTrace(System.err)將錯誤傳送給標準錯誤流,通常這比錯誤輸出到System.out要好,因為System.out也許會被重定向,System.err不會,更容易引起使用者注意

呼叫在Throwable類(Exception 從此類繼承)中宣告的printStackTrace()方法,將列印從方法呼叫處直到異常丟擲處,資訊被髮送到System.out。但如果呼叫了預設版本e.printStackTrace(),則輸入到標準錯誤流。

異常說明

屬於方法宣告的一部分,緊跟在引數列表之後,使用了附加的關鍵字throws,後面接一個所有潛在異常型別的列表。使你告知客戶端程式設計師某個方法可能會丟擲的異常型別,然後客戶端程式設計師就可以進行相應的處理。程式碼必須與異常保持一致,如果方法裡面的程式碼產生了異常,卻沒有進行處理,編譯器會發現這個問題

異常丟失

某些特殊的方式使用finally造成異常丟失

package exceptions;

class VeryImportantException extends Exception {
    @Override
    public String toString() {
        return "A very important exception!";
    }
}

class ImportantException extends Exception {
    @Override
    public String toString() {
        return "An important exception!";
    }
}
class HoHumException extends Exception {//HoHum令人生厭的
    @Override
    public String toString() {
        return "A trivial exception!";//trivial:不重要的
    }
}


public class LostMessage {
    void f() throws VeryImportantException {
        throw new VeryImportantException();
    }

    void g() throws ImportantException {
        throw new ImportantException();
    }

    void dispose() throws HoHumException {
        throw new HoHumException();
    }

    public static void main(String[] args) {
        try {
            LostMessage lm = new LostMessage();
            try {
                lm.f();
            } finally {
                lm.dispose();
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
/* 
A trivial exception!
*/

更加簡單的丟失異常的方式:從finally子句中返回

package exceptions;

public class ExceptionSilencer {
    public static void main(String[] args) {
        try {
            throw new RuntimeException();
        } finally {
            return;
        }
    }
}

異常匹配

丟擲異常的時候,異常處理系統會按照程式碼的書寫順序找出“最近”的處理程式,找的匹配的處理程式之後,它就認為異常得到處理,然後不再查詢。查詢的時候並不要求異常完全匹配,派生類的物件也可以匹配其基類的處理程式。

package exceptions;

class Annoyance extends Exception {}
class Sneeze extends Annoyance {}

public class Human {
    public static void main(String[] args) {
        try {
            throw new Sneeze();
        } catch (Sneeze s) {
            System.out.println("Caught Sneeze");
        } catch (Annoyance a) {
             System.out.println("Caught Annoyance");
        }

        try {
            throw new Sneeze();
        } catch (Annoyance a) {
            System.out.println("Caught Annoyance");
        }
    }
}

基本日誌功能(將輸出 記錄到日誌中)

package exception;

import java.util.logging.*;
import java.io.*;
class LoggingException extends Exception {
    private static Logger logger = Logger.getLogger("LoggingException");    
    public LoggingException() {
        StringWriter trace = new StringWriter();
        printStackTrace(new PrintWriter(trace));
        logger.severe(trace.toString());
    }

}
public class LoggingExceptions  {
    public static void main(String[] args) {
        try {
            throw new LoggingException();
        } catch(LoggingException e) {
            System.err.println("Caught" + e);
        }
        try {
            throw new LoggingException();
        } catch (LoggingException e) {
            System.err.println("Caught" + e);
        }
    }

}
public static Logger getLogger(String name)
//name是Logger的名稱,此名稱建立過再次建立則返回原來的Logger
logger.severe(trace.toString());
/*output:
8月 12, 2020 5:02:56 下午 exception.LoggingException <init>
嚴重: exception.LoggingException at   exception.LoggingExceptions.main(LoggingExceptions.java:17)*/
StringWriter trace = new StringWriter();
public StringWriter() {
        buf = new StringBuffer();
        lock = buf;
}

Logger級別

severe 嚴重
warning 警告
info 資訊
config 配置
fine 良好
finer 較好
finest 最好
all 開啟所有級別日誌記錄
off 關閉所有級別日誌記錄