Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throw custom exception from interface implement method

Tags:

java

I am trying to add a custom throws clause to a method definied by an interface. This is not possible. How could I bypass it? Here is some code:

private void sendRequestToService(final ModuleRequest pushRequest) 
{

    ServiceConnection serviceConnection = new ServiceConnection()
    {

        public void onServiceConnected(ComponentName name, IBinder service) 
        {

            try
            {

                //some lines..

            } catch (RemoteException e)
            {
                throw new RuntimeException(new UnavailableDestException()) ;
            }
        }


    };

}

Any idea how I could throw my custom exception?

like image 452
rayman Avatar asked Dec 03 '22 11:12

rayman


1 Answers

There are two types of exceptions, checked and unchecked. Any Throwable is either one or the other.

An example of a checked exception is IOException; probably the most (in)famous unchecked exception is NullPointerException.

Any checked exceptions that a method may throw must be declared in its throws clause. When you @Override a method (either implementing an interface method or overriding an inherited method from a superclass), certain requirements must be met, and one of them is that the throws clause must not cause a conflict. Simplistically speaking, subclasses/implementations can throw LESS, not MORE checked exceptions.

An unchecked exception is defined as RuntimeException and its subclasses, and Error and its subclasses. They do not have to be declared in a method's throws clause.

So in this particular case, if you want to throw a CustomException in an implementation of an interface method that does not list it in its throws clause, you can make CustomException extends RuntimeException, making it unchecked. (It can also extends any subclass of RuntimeException, e.g. IllegalArgumentException or IndexOutOfBoundsException may be more appropriate in some cases).

This will allow you to compile the code as you desire, but note that the choice between choosing checked vs unchecked exception should not be taken too lightly. This is a contentious issue for many, and there are many factors to consider other than just getting the code to compile the way you want it. You may want to consider a redesign of the interface rather than having implementors throwing various undocumented unchecked exceptions not specified by the interface contract.

References

  • JLS 11.2 Compile-Time Checking of Exceptions
  • JLS 8.4.6 Method Throws

    A method that overrides or hides another method, including methods that implement abstract methods defined in interfaces, may not be declared to throw more checked exceptions than the overridden or hidden method.

Related questions

  • In Java, when should I create a checked exception, and when should it be a runtime exception?
  • When to choose checked and unchecked exceptions
  • The case against checked exceptions

See also

  • Effective Java 2nd Edition
    • Item 58: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors
    • Item 59: Avoid unnecessary use of checked exceptions
    • Item 60: Favor the use of standard exceptions
    • Item 61: Throw exceptions appropriate to the abstraction
    • Item 62: Document all exceptions thrown by each method

Workaround "solution"

If a redesign is impossible, then wrapping your CustomException in a RuntimeException (or its subclass) will "work". That is, instead of:

// ideal solution, not possible without redesign

@Override public static void someMethod() throws CustomException {
    throw new CustomException();
}

//...
try {
    someMethod();
} catch (CustomException e) {
    handleCustomException(e);
}

You can, should you insist, do the following:

// workaround if redesign is not possible
// NOT RECOMMENDED!

@Override public static void someMethod() {
    throw new RuntimeException(new CustomException());
}

//...
try {
    someMethod();
} catch (RuntimeException e) { // not catch(CustomException e)

    if (e.getCause() instanceof CustomException) {
        handleCustomException((CustomException) e.getCause());
    } else {
        throw e; // preserves previous behavior
    }

}

It needs to be reiterated that this is NOT a recommendable technique in general. You should fix the problem at the design level if at all possible, but barring that, this is indeed a possible workaround.

like image 155
polygenelubricants Avatar answered Jan 02 '23 17:01

polygenelubricants