2

I want to modify the ArithmeticException output message. So, for that i did few experiments. I extended the ArithmeticException class byExtenderClass class. The point of this question is not only to find the solutions to modify the ArithmeticException exception message but also to tell why some of cases below are working as expected but some are not? Following are the cases along with their outputs:

Case 1:

// 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{
    // ...
}

Output:

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

Result: Works fine as expected.


Case 2:

// 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{
    // ...
}

Output:

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

Result: Means that the throw/catch is not fired. Why the ExtenderClass is not fired? In fact its extending the ArithmeticException class?


Case 3:

// 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{
    // ...
}

Output:

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

Result: Works fine as expected.


Case 4:

// 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{
    // ...
}

Output:

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

Result: Means that the throw/catch is not fired. Why the ExtenderClass is not fired? In fact its extending the ArithmeticException class?


Why the ExtenderClass class that extends the ArithmeticException is not fired? But when i use the ArithmeticException directly, it gets fired.

Naman
  • 27,789
  • 26
  • 218
  • 353
Stack Overflow
  • 1
  • 5
  • 23
  • 51
  • because the `ArithmeticException` class is fired internally by the compiler and on the same time it gets fired if it is in the next `catch` case, may be that is the case. I am not an expert in java but sharing knowledge as much as you have is not bad. – Stack Overflow Dec 31 '18 at 06:06

5 Answers5

2

While you have declared a custom exception as a subclass of ArithmeticException, there is no way that you can get a / b to throw your custom exception. The JLS specifies that (integer) division by zero will throw ArithmeticException; see JLS 15.17.2 paragraph 3.

Since the exception that is being thrown is ArithmeticException, you won't be able to catch it as your custom exception.

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

will catch ExtenderClass and subclasses of ExtenderClass. ArithmeticException is not a subclass of ExtenderClass, so the above won't catch it.


Your reason for creating ExtenderClass is ...

I want to modify the ArithmeticException output message.

You would be better off writing some special-case code to substitute a different message for the "/ zero" message when you print it out.

Or ....

try {
   c = a / b;      
} catch (ArithmeticException ex) {
   thrown new ExtenderClass("Division by zero is cool!, ex);
}
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
2

Creating a sub-class of ArithmeticException doesn't cause an instance of that sub-class to be thrown when you divide an int by 0.

Dividing an int by 0 will always throw the base ArithmeticException class.

Your ExtenderClass will only be thrown if you throw it explicitly in your code:

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

In the only case you explicitly throw ExtenderClass (case 4), that throw statement is never reached, since the previous statement causes ArithmeticException to be thrown.

Eran
  • 387,369
  • 54
  • 702
  • 768
2

As explained in the comments:

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);
}
xingbin
  • 27,410
  • 9
  • 53
  • 103
1

Reviewing your cases:

1) You cause and catch an ArithmeticException as expected. ExtenderClass is un-used.

2) An ArithmeticException is thrown and is not caught by your code as ExtenderClass is more specific than ArithmeticException.

3) You cause and catch an ArithmeticException as expected. Note: execution does not reach the point where you explicitly throw an ArithmeticException.

4) You cause an ArithmeticException with the line c = a / b and it is not caught by your code as ExtenderClass is more specific than ArithmeticException. Execution does not reach the point where you explicitly throw an ExtenderClass.

dave
  • 11,641
  • 5
  • 47
  • 65
1

Nice observation.

Please find my explanations:

NOTE:

  • As per you code snippet ArithmeticException is a SuperClass and ExtenderClass is SubClass

  • In Java catch block will execute only if the exception defined inside it is same as the exception thrown in try block or broader than try block.


EXPLANATIONS:

  • Case 1
    Here you are throwing ArithmeticException and catching it by the same class, so catch block is executing as expected.

  • Case 2
    Here you are throwing ArithmeticException at line no. 9 c = a / b; and trying to catch by its subclass which is not possible.
    So the exception is not been handled in catch block. You should catch by same or Broader Exception(Super class).

  • Case 3
    This case is similar to case 2 except you are catching by Same Exception(ArithmeticException) and throwing ArithmeticException 2 times

    try{ c = a / b; throw new ArithmeticException(); }catch(ArithmeticException e){ System.out.println("I caught: " + e); }
    This line throw new ArithmeticException(); will not execute as exception thrown in previous line. Here at line c = a / b; you thrown ArithmeticException and catching the same in catch block so it works as expected

  • Case 4
    In this case you are throwing ArithmeticException first then ExtenderClass so only 1st exception will be thrown and control will never goes to second as per the below code.

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

    Here you are trying to catch by Subclass(ExtenderClass) which is not possible. so catch block will not handle the exception.

TheSprinter
  • 1,523
  • 17
  • 30