首頁  >  文章  >  Java  >  Java關鍵字throw、throws、Throwable怎麼用

Java關鍵字throw、throws、Throwable怎麼用

WBOY
WBOY轉載
2023-05-10 11:28:051841瀏覽

    throw,意思是「投擲、拋、丟」。 Throw、Throws和Throwable三者都用於異常處理。

    1. Throwable

    Throwable在Java中是異常處理這個分支的頂級父類,其它所有異常處理的實作都依賴Throwable

    開啟Java官方文件( Java8版本),找到Throwable,它的直接子類別為Error和Exception。

    Java關鍵字throw、throws、Throwable怎麼用

    Error和Exception兩者的特點在於Error異常程式無法處理,只能交由人工介入修改程式碼,例如堆疊溢出、堆疊溢出等等;而Exception異常可提前發覺,並作出有效處理。

    1.1 擴充-Error

    在Error中,常見的有堆疊溢位和堆疊溢位等等。

    Java關鍵字throw、throws、Throwable怎麼用

    舉個例子,StackOverflowError

    public class ErrorTest {
        public static void main(String[] args) {
            main(args);
        }
    }

    無限遞歸,執行這個程式就會報到堆疊溢位例外。

    Java關鍵字throw、throws、Throwable怎麼用

    再例如堆異常,OutOfMemoryError

    public class ErrorTest {
        public static void main(String[] args) {
            Integer[] testArray = new Integer[1024*1024*1024];
        }
    }

    Java關鍵字throw、throws、Throwable怎麼用

    1.2 擴充-Exception

    在Exception中就有非常多我們所熟知的異常情況了,像是NullPointerException(空指標異常)、ArrayIndexOutOfBoundsException(陣列下標越界)、NumberFormatException(數位格式化例外)等等。

    public class ExceptionTest {
        public static void main(String[] args) {
            int[] testArray = null;
            System.out.println(testArray[0]);  //空指针异常
        }
    }
    public class ExceptionTest {
        public static void main(String[] args) {
            int[] testArray = new int[3];
            System.out.println(testArray[3]);   //数组下标越界
        }
    }
    public class ExceptionTest {
        public static void main(String[] args) {
            String num = "abc";
            System.out.println(Integer.parseInt(num));    //数字格式化异常
        }
    }

    2. throws

    throws應用在方法宣告處,指明此方法執行時可能會出現的例外類型。一旦該方法執行時出現異常,就會在異常代碼處產生一個異常類別的對象,此對象滿足Throws後的異常類型時,就會被拋出。這裡有兩個過程,程式碼有異常時

    1. 產生一個異常物件;

    2. throws捕獲到這個異常,將異常物件拋出

    throws和try-catch-finally一起稱為異常處理的兩種方式。

    try-catch-finally是在出現異常時主動處理掉異常,使得程式可以繼續執行下去;而throws捕獲到異常之後向上拋出異常對象,不去真正地處理這個異常。

    所謂向上拋出異常對象,是將例外物件交給呼叫者去處理,例如方法A呼叫方法B,B透過throws拋出異常,而A可以選擇使用try-catch-finally處理掉異常,也可以透過throws繼續向上拋出異常對象,直到異常被真正處理掉。如果一直沒有方法去處理異常,異常物件最終會被拋給JVM,導致程式停止運作。

    @Test
    public void throwsTest(){   //调用者解决抛出的异常
        try{
            formatChange("abc");
        }
        catch (NumberFormatException e){
            System.out.println("转换格式错误!");
        }
        catch (Exception e){
            System.out.println("出现错误");
        }
    }
    private int formatChange(String str) throws NumberFormatException{    //出现异常向上抛出
        return Integer.parseInt(str);
    }

    2.1 擴充

    ——如何選擇try-catch-finally還是throws?

    當一個方法中存在異常需要處理,在大多數情況下,既可以選擇try-catch-finally直接處理掉這個異常,也可以選擇throws向上拋出異常,交給呼叫者去處理(異常拋到最後,總要有一方真正地去處理這個異常,怎麼處理?還是用try-catch-finally唄),在選擇上比較自由,但是,出現以下兩種情況時,需要遵循一定的規則(如有補充,請指出)。

    • 如果父類別中被重寫的方法沒有使用throws拋出異常,則子類別重寫的方法也不能使用throws拋出異常,也就意味著這種情況必須使用try-catch-finally去處理。

    • 在方法A中,先後呼叫了另外的幾種方法,這幾種方法是遞進關係執行的且其中許多方法都存在異常需要處理,這種情況建議被呼叫的幾個方法使用throws向上拋出異常,在方法A中,使用try-catch-finally統一處理掉這些異常。

    針對第一條,這是一個規定,子類別中重寫的方法使用throws拋出的異常必須不大於父類別中被重寫的方法拋出異常的範圍。舉個例子,父類別中的方法B拋出NullPointerException異常,則子類別中重寫B方法就不能拋出如Exception這種比NullPointerException範圍更大的異常;如果父類別中被重寫的方法沒有拋出任何異常,則子類別更不能拋出異常。

    為什麼?展示一段程式碼。

    //假设父类中的方法B抛出NullPointerException异常,子类中的方法B可以抛出Exception
    private void test(ParentClassTest parent){
        try{
            parent.B();
        }
        catch(NullPointerException e){
            System.out.println("出现了空指针异常");
        }
    }

    在本範例中,假設父類別中的方法B拋出NullPointerException異常,子類別中重寫的方法B可以拋出Exception。那麼傳進給test方法的參數如果是父類別的實例化對象,那麼呼叫test方法就沒有任何問題。如果傳進的參數是子類別的實例化對象,再去呼叫子類別重寫的方法B,那麼就有可能拋出Exception異常,try-catch結構就壓不住這個異常了,這顯然是一個不合理的操作。

    针对第二条,假设方法A中调用了方法C、D、E,这三个方法都有可能产生异常,且存在递进关系,也就是D、E执行需要C执行完成、E执行依赖C、D执行完成。那么就推荐在C、D、E中向上抛出异常,在方法A中集中处理。为什么?如果C、D、E都是向上抛出异常,而A使用try-catch-finally去处理这个异常,如果某个方法真的出现异常,则不再继续执行。而如果C、D、E都使用try-catch-finally直接解决掉异常,那么即使产生了异常,方法A也不会接收到异常的产生,那么还会接着往下执行,但是C出现了异常,再执行D、E没有任何意义。

    3. throw

    如果在程序编写时有手动抛出异常的需求,则可以使用throw

    throw使用在方法体内。与try-catch-finally和throws都不同,异常处理的两个阶段:1.遇到异常,生成异常对象;2.捕获到异常,进行抛出或处理。try-catch-finally和throws都处在第二个阶段,都是捕获到异常后的相关处理,一般使用系统根据异常类型自动生成的异常对象进行处理。而throw应用在第一阶段,手动地产生一个异常对象。

    举一个例子,判断一个数值是否为非负数,如果为负数,则抛出异常。

    class ThrowTest{
        private int Number;
        public void judge(int num){
            if(num>=0){
                this.Number = num;
            }
            else{
                throw new RuntimeException("传入参数为负数");
            }
        }
    }
    @Test
    public void test2(){
        ThrowTest throwTest = new ThrowTest();
        throwTest.judge(-100);
    }

    成功抛出异常。

    Java關鍵字throw、throws、Throwable怎麼用

    使用try-catch捕获一下异常。

    @Test
    public void test2(){
        ThrowTest throwTest = new ThrowTest();
        try{
            throwTest.judge(-100);
        }
        catch (RuntimeException e){
            System.out.println(e.getMessage());
        }
    }

    Java關鍵字throw、throws、Throwable怎麼用

    如果把throw抛出的异常改为Exception,则直接报错,也就是不能编译。Exception包含两种异常:编译时异常和运行时异常,前者在编译前就要检查是否有可能产生编译时异常;后者是在编译后运行时才会判断的异常。而throw new Exception包含了编译时异常,需要显式处理掉这个异常,怎么处理?try-catch-finally或者throws

    Java關鍵字throw、throws、Throwable怎麼用

    class ThrowTest{
        private int Number;
        public void judge(int num) throws Exception{
            if(num>=0){
                this.Number = num;
            }
            else{
                throw new Exception("传入参数为负数");
            }
        }
    }

    调用方也要随着进行更改。

    @Test
    public void test2(){
        ThrowTest throwTest = new ThrowTest();
        try{
            throwTest.judge(-100);
        }
        catch (RuntimeException e){
            System.out.println(e.getMessage());
        }
        catch (Exception e){
            System.out.println(e.getMessage());
        }
    }

    Java關鍵字throw、throws、Throwable怎麼用

    3.1 扩展

    ——自定义异常类

    throw还可以抛出自定义异常类。

    自定义异常类的声明需要继承于现有的异常体系。

    class MyException extends RuntimeException{
        static final long serialVersionUID = -703489719076939L;   //可以认为是一种标识
        public MyException(){}
        public MyException(String message){
            super(message);
        }
    }

    此时我们可以抛出自定义的异常

    class ThrowTest{
        private int Number;
        public void judge(int num) throws MyException{
            if(num>=0){
                this.Number = num;
            }
            else{
                throw new MyException("不能输入负数");
            }
        }
    }

    调用者修改

    @Test
    public void test2(){
        ThrowTest throwTest = new ThrowTest();
        try{
            throwTest.judge(-100);
        }
        catch (MyException e){
            System.out.println(e.getMessage());
        }
    }

    Java關鍵字throw、throws、Throwable怎麼用

    以上是Java關鍵字throw、throws、Throwable怎麼用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除