Java - 为什么不调用 ArithmeticException class 的 subclass?

Java - Why the subclass of ArithmeticException class is not called?

我想修改 ArithmeticException 输出消息。所以,为此我做了一些实验。我将 ArithmeticException class 扩展了 ExtenderClass class。这个问题的重点不仅是找到修改 ArithmeticException 异常消息的解决方案,而且还要说明为什么下面的某些情况按预期工作而有些情况却没有?以下是案例及其输出:

案例一:

// Both the classes are in the same file 'MyClass.java'
class MyClass{
    public static void main(String args[]){

        int a,b,c;
        a = 1;
        b = 0;

        try{
            c = a / b;
        }catch(ArithmeticException e){
            System.out.println("I caught: " + e);
        }

    }
}

class ExtenderClass extends ArithmeticException{
    // ...
}

输出:

I caught: java.lang.ArithmeticException: / by zero

结果:按预期工作正常。


案例二:

// Both the classes are in the same file 'MyClass.java'
class MyClass{
    public static void main(String args[]){

        int a,b,c;
        a = 1;
        b = 0;

        try{
            c = a / b;
        }catch(ExtenderClass e){
            System.out.println("I caught: " + e);
        }

    }
}

class ExtenderClass extends ArithmeticException{
    // ...
}

输出:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at MyClass.main(MyClass.java:9)

结果:意味着 throw/catch 没有被触发。为什么 ExtenderClass 没有被解雇?事实上它扩展了 ArithmeticException class?


案例三:

// Both the classes are in the same file 'MyClass.java'
class MyClass{
    public static void main(String args[]){

        int a,b,c;
        a = 1;
        b = 0;

        try{
            c = a / b;
            throw new ArithmeticException();
        }catch(ArithmeticException e){
            System.out.println("I caught: " + e);
        }

    }
}

class ExtenderClass extends ArithmeticException{
    // ...
}

输出:

I caught: java.lang.ArithmeticException: / by zero

结果:按预期工作正常。


案例四:

// Both the classes are in the same file 'MyClass.java'
class MyClass{
    public static void main(String args[]){

        int a,b,c;
        a = 1;
        b = 0;

        try{
            c = a / b;
            throw new ExtenderClass();
        }catch(ExtenderClass e){
            System.out.println("I caught: " + e);
        }

    }
}

class ExtenderClass extends ArithmeticException{
    // ...
}

输出:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at MyClass.main(MyClass.java:9)

结果:意味着 throw/catch 没有被触发。为什么 ExtenderClass 没有被解雇?事实上它扩展了 ArithmeticException class?


为什么扩展 ArithmeticExceptionExtenderClass class 没有被触发?但是当我直接使用 ArithmeticException 时,它会被触发。

正在审查您的案例:

1) 您按预期引发并捕获了 ArithmeticExceptionExtenderClass 未使用。

2) ArithmeticException 被抛出并且没有被 您的 代码捕获,因为 ExtenderClass 更具体 ArithmeticException.

3) 您按预期引发并捕获了 ArithmeticException。注意:执行没有达到你明确抛出 ArithmeticException.

的地步

4) 你用行 c = a / b 引起了一个 ArithmeticException 并且它没有被 你的 代码捕获,因为 ExtenderClassArithmeticException 更具体 。执行未达到您明确抛出 ExtenderClass.

的程度

虽然您已将自定义异常声明为 ArithmeticException 的子类,但您无法让 a / b 抛出您的自定义异常。 JLS 指定(整数)除以零将抛出 ArithmeticException;参见 JLS 15.17.2 第 3 段。

由于抛出的异常是 ArithmeticException,您将无法将其作为自定义异常捕获。

try {
   c = a / b;      
} catch (ExtenderClass ex) {
   ...
}

将捕获 ExtenderClassExtenderClass 的子类。 ArithmeticException 不是 ExtenderClass 的子类,所以上面的 不会 捕获它。


您创建 ExtenderClass 的原因是...

I want to modify the ArithmeticException output message.

您最好编写一些特殊情况的代码,以便在打印时用不同的消息替换“/ zero”消息。

或者....

try {
   c = a / b;      
} catch (ArithmeticException ex) {
   thrown new ExtenderClass("Division by zero is cool!, ex);
}

创建 ArithmeticException 的子 class 不会导致在将 int 除以 0 时抛出该子 class 的实例。

int 除以 0 将始终抛出基数 ArithmeticException class.

您的 ExtenderClass 只有在您在代码中明确抛出它时才会被抛出:

    try {
        c = a / b;
    } catch(ArithmeticException e) {
        throw new ExtenderClass ();
    }

在您明确抛出 ExtenderClass 的唯一情况下(案例 4),该抛出语句永远不会到达,因为前面的语句导致 ArithmeticException 被抛出。

如评论中所述:

try{
    c = a / b; // ArithmeticException was thrown at this line
    throw new ExtenderClass(); // So this line was not executed 
}catch(ExtenderClass e){  // This line will catch ExtenderClass and it's sub class. However, ArithmeticException is super class of ExtenderClass, not it's sub class, so it won't be caught
    System.out.println("I caught: " + e);
}

很好的观察。

请看我的解释:

注意:

  • 根据您的代码片段 ArithmeticExceptionSuperClassExtenderClass子类

  • In Java catch 块只有在其内部定义的异常与 [= 中抛出的异常相同时才会执行57=]try 块或比 try 块更宽。


解释:

  • 案例一
    这里你抛出 ArithmeticException 并用相同的 class 捕获它,所以 catch 块按预期执行。

  • 案例二
    在这里,您在第 1 行抛出 ArithmeticException。 9 c = a / b; 并试图通过它的 subclass 来捕捉,这是不可能的。
    所以异常没有在 catch 块中处理。 您应该通过相同或 Broader Exception(Super class).

  • 捕获
  • 案例三
    这种情况与情况 2 类似,只是您被 Same Exception(ArithmeticException) 捕获并抛出 ArithmeticException 2 次

    try{ c = a / b; throw new ArithmeticException(); }catch(ArithmeticException e){ System.out.println("I caught: " + e); }
    这一行 throw new ArithmeticException(); 不会作为上一行抛出的异常执行。 在第 c = a / b; 行,你抛出 ArithmeticException 并在 catch 块中捕获相同的内容,因此它按预期工作

  • 案例4
    在这种情况下,您首先抛出 ArithmeticException 然后 ExtenderClass 因此只会抛出第一个异常并且控制永远不会按照下面的代码转到第二个。

    try{
        c = a / b;
        throw new ExtenderClass();
    }catch(ExtenderClass e){
        System.out.println("I caught: " + e);
    }
    

    在这里你试图通过 Subclass(ExtenderClass) 捕捉,这是不可能的。所以 catch 块将不会处理异常。