1
public class First {
protected void method1() throws CustomException {
    int number=10/0;
    System.out.println("method 1" + number);
    throw new CustomException("Divided by zero");
}
public class Second extends First {
protected void method2() {
        method1();
    
}
public class Third extends Second {
protected void method3(){
    try {
        method2();
        }
        catch (CustomException ex)
        {
            System.out.println("Caught the exception");
            System.out.println(ex.getMessage());
        } 
}

In this code first throws an exception and I want to catch it from third (second will not handle error). But second's method call won't let me pass. How can I fix this?

melisa
  • 37
  • 6
  • 1
    by not calling the method from the second class. Make that class abstract, and force the user to use the child class – Stultuske Aug 18 '20 at 11:40
  • 1
    Maybe explain more why that's the use case/implementation. There are multiple solutions for this answer, such cutting the middle man, not declaring the `CustomException` in `method1`, etc. – Gustavo Kawamoto Aug 18 '20 at 11:42
  • I have to catch in third and log its' details in a file. But I can't delete the second. Because it's kinda homework. – melisa Aug 18 '20 at 11:49
  • @Stultuske Sorry but I don't understand what do you mean – melisa Aug 18 '20 at 11:51
  • 1
    if the user is allowed to directly call the method in the parent class, it is not possible to say that the child class must handle the exception. so, make sure only the child classes methods are publicly visible – Stultuske Aug 18 '20 at 12:45
  • Possible duplicate of this [answer](https://stackoverflow.com/a/46881785/12695027), that explains it better than I did. I got the impression that is wasn't really the subclassing that posed the problem :) – Scratte Aug 19 '20 at 11:15

1 Answers1

9

For checked exceptions (not any RuntimeException), they must be either handled or thrown by the method that calls another method that throws the exception. This is also explained in more depth in the tutorial by Oracle on Exceptions.

This example is based on your code:

class Testing{
  public static void main(String[] args) {
    Third t = new Third();
    t.method3();
  }
}

and it will print:

Caught the exception
Divided by zero

Added the missing implementation of CustomException:

class CustomException extends Exception{
  CustomException(){
    super();
  }
  CustomException(String message){
    super(message);
  }
}

Note that your code would never get to actually throwing your exception, as division by zero would be thrown first. ArithmeticException is a RuntimeException and therefore not a checked exception, and it doesn't need or warrant any declaration. I've removed it so your exception is thrown:

class First {
  protected void method1() throws CustomException {
  // will cause "java.lang.ArithmeticException: / by zero" not CustomException
  //  int number=10/0;
  //  System.out.println("method 1" + number);
    throw new CustomException("Divided by zero");
  }
} // missing end brace

The reason why your Second's method call "won't let me pass" is because you're throwing an Exception in method1 which you are calling in your Second's method call. So you need to either wrap your call to method1() in a try-catch block, or throws it. Since you "want to catch it from third", you need to throws it in the declaration of the method:

class Second extends First {
  // error: unreported exception CustomException; must be caught or declared to be thrown
  // protected void method2() {  // your version

  protected void method2() throws CustomException {
    method1();
  }
} // missing end brace

This is unchanged, except for the added brace:

class Third extends Second {
  protected void method3(){
    try {
      method2();
    } catch (CustomException ex) {
      System.out.println("Caught the exception");
      System.out.println(ex.getMessage());
    } 
  } 
} // missing end brace
Jeanne Dark
  • 1,151
  • 5
  • 20
  • 30
Scratte
  • 3,056
  • 6
  • 19
  • 26