Skip to content

Latest commit

 

History

History
45 lines (32 loc) · 2.08 KB

2862.md

File metadata and controls

45 lines (32 loc) · 2.08 KB

Back to questions

Solution to 2862: Exceptions and inheritance (ii)

See code at solutions/code/tutorialquestions/question2862

The reason that the classes compile even though foo() in B throws a different exception from foo() in A is that the exception, MyExceptionD, thrown by foo in B is a subclass of MyExceptionC thrown by foo in A. It is OK when overriding a method to narrow the types of exceptions that can be thrown. As discussed in the solution to question 74d2, this ensures that the overridden method behaves (in terms of the exceptions it may throw) better than the superclass method.

We call this change of exception types during overriding covariant: co- because the subclass method throws a subclass of the exception thrown by the superclass method.

If we remove @Override from foo() in B, add

import java.io.IOException;

to the top of class B and change the declaration of foo() in B to:

void foo() throws IOException {
  throw new IOException();
}

then class B does not compile. The problem is that the compiler still thinks we are trying to override foo in A, and tells us that the exception type IOException that we have specified does not match the exception type specified for foo in A, which is MyExceptionC.

This tells us that in Java we cannot overload methods based on the types of exceptions they throw.

Finally, the demo class given in the question does not compile because exception handling is checked by the compiler based on the apparent types of variables. Variable myB has apparent type A, even though it is initialised to have actual type B. Apparent type A means that the compiler thinks the call myB.foo() may throw an exception of type MyExceptionC, which is not sufficiently covered by the catch clause for exceptions of type MyExceptionD.

This can be fixed by changing the apparent type of myB to B, or by down-casting myB to type B at the call site, or by catching an exception of type MyExceptionC.