Search code examples
javacompiler-errorsmethod-referencecatch-block

Compile error for method reference in multiple exception handling


There is an interesting situation I have encountered. I have 2 exception classes MyException1 and MyException2. During multiple catch(MyException1 | MyException2 ex) SonarLint suggests using method reference (ex::getExitCode) instead of the lambda expression (()=>ex.getExitCode()). But if I follow the suggestion this time the compiler complains saying "Cannot resolve method 'getExitCode'". If I remove one of the exceptions compilation succeeds. So the code compiles only with one exception catch or I have to cast the class to the ancestor of the two. And if I cast it, SonarLint this time warns me about the unnecessary cast. Can someone explain what is going on here?

MyException1

public class MyException1 extends RuntimeException implements ExitCodeGenerator {
    public MyException1 (String message, Throwable throwable) {
        super(message, throwable);
    }

    @Override
    public int getExitCode() {
        return -2;
    }
}

MyException2

public class MyException2 extends RuntimeException implements ExitCodeGenerator {
    public MyException2 (String message, Throwable throwable) {
        super(message, throwable);
    }

    @Override
    public int getExitCode() {
        return -2;
    }
}

Compile error

...
} catch (MyException1 | MyException2 ex) {
    System.exit(SpringApplication.exit(event.getApplicationContext(), ex::getExitCode);
} 
...

Compiled

...
} catch (MyException1 | MyException2 ex) {
    System.exit(SpringApplication.exit(event.getApplicationContext(), ((ExitCodeGenerator)ex)::getExitCode);
} 
...

OR

Compiled

...
} catch (MyException1 ex) {
    System.exit(SpringApplication.exit(event.getApplicationContext(), ex::getExitCode);
} 
...

Solution

  • The problem of the multicatch is the type of ex.

    It will be Exception and not ExitCodeGenerator that's why you have to cast the exception.