What to put in the throws clause of an interface method?

Suppose I have interface I and two classes A and B that implement it. An implementation of method f this interface in A throws one set of exceptions, and an implementation in B throws another set. The only common ancestor of these exceptions is java.lang.Exception . Is it possible to declare f throwing java.lang.Exception in this case? Any other alternatives?

The reason I'm asking is because, on the one hand, java.lang.Exception seems too general to me, and the other, listing all exceptions, seems impractical, given other possible implementations.

Example:

 interface I { void f() throws Exception; } class A implements I { public void f() throws IOException {} } class B implements I { public void f() throws InterruptedException {} } 
+4
source share
3 answers

The reason for using the interface is to abstract the implementation details.

By throwing these exceptions, you are revealing implementation details that should probably be abstracted.

Perhaps it would be better to define a new exception. Then each implementation of f () will catch those exceptions that it knows about, and instead throw a new exception so that you have:

 interface I { void f() throws MyException; } class A implements I { public void f() throws MyException { try { ... } catch (IOException e) { throw new MyException(e); } } } class B implements I { public void f() throws MyException { try { ... } catch (InterruptedException e) { throw new MyException(e); } } } 

Concluding the implementation exception, you expose it to the caller anyway, and this may bite you when you call remote methods. In these cases, you need to do more work to return useful information in a general way.

Edit
There seems to be a bit of a debate about the right approach.

When we call f (), we need the code:

 I instanceOfI = getI(); try { instanceOfI.f(); } catch ( /* What should go here ? */ ) 

This boils down to what is a good Exception class to include a catch block.
With the OP source code, we could catch an Exception , and then maybe try to see which subclass we have or is not dependent on requirements. Or we could individually catch each subclass, but then we would have to add catch blocks when new implementations throw different exceptions.

If we used Runtime exceptions, it would be almost the same, except that we could alternatively defer exception handling to the caller method, without even giving the possibility of exceptions of any thought.

If we used my suggestion to use a new wrapped exception, this means that we should catch MyException , and then try to find out what additional information is available. This is essentially very similar to using an exception, but requires additional work for the limited benefit of a bespoke exception that can be tailored to the target.

+14
source

It seems a bit backward. You should throw exceptions that are relevant and possibly specific to your interface, or not at all. Modify implementations to wrap a common class of exceptions (although not Exception ). If you cannot handle this, you can wrap exceptions in implementations with a RuntimeException.

+3
source

You can just declare the exceptions you throw

 void f() throws IOException, InterruptedException; 

If you use a decent IDE, it will fix it for you. I just throw an exception in the method, which the IDE gives options to add to the method proposal and its interface.

+1
source

All Articles