I was going through SCJP 6 book by Kathe sierra and came across this explanations of throwing exceptions in overridden method. I quite didn't get it. Can any one explain it to me ?
The overriding method must NOT throw checked exceptions that are new or broader than those declared by the overridden method. For example, a method that declares a FileNotFoundException cannot be overridden by a method that declares a SQLException, Exception, or any other non-runtime exception unless it's a subclass of FileNotFoundException.
The subclass's overriding method can only throw multiple checked exceptions that are subclasses of the superclass's method's checked exception, but cannot throw multiple checked exceptions that are unrelated to the superclass's method's checked exception
To illustrate this, consider:
Suppose you then write:
This will give you a compilation error, because r.close() throws an IOException, which is broader than FileNotFoundException.
To fix this, if you write:
You will get a different compilation error, because you are implementing the perform(...) operation, but throwing an exception not included in the interface's definition of the method.
Why is this important? Well a consumer of the interface may have:
If the IOException were allowed to be thrown, the client's code is nolonger correct.
Note that you can avoid this sort of issue if you use unchecked exceptions. (I am not suggesting you do or don't, that is a philosophical issue)
The overriding method CAN throw any unchecked (runtime) exception, regardless of whether the overridden method declares the exception
Example:
Java is giving you the choice to restrict exceptions in the parent class, because it's assuming the client will restrict what is caught. IMHO you should essentially never use this "feature", because your clients may need flexibility down the road.
Java is an old language that is poorly designed. Modern languages don't have such restrictions. The easiest way around this flaw is make your base class
throw Exception
always. Clients can throw more specific Exceptions but make your base classes really broad.The overriding method must NOT throw checked exceptions that are new or broader than those declared by the overridden method.
This simply means when you override an existing method, the exception that this overloaded method throws should be either the same exception which the original method throws or any of its subclasses.
Note that checking whether all checked exceptions are handled is done at compile time and not at runtime. So at compile time itself, the Java compiler checks the type of exception the overridden method is throwing. Since which overridden method will be executed can be decided only at runtime, we cannot know what kind of Exception we have to catch.
Example
Let's say we have class
A
and its subclassB
.A
has methodm1
and classB
has overridden this method (lets call itm2
to avoid confusion..). Now let's saym1
throwsE1
, andm2
throwsE2
, which isE1
's superclass. Now we write the following piece of code:Note that
m1
is nothing but a call tom2
(again, method signatures are same in overloaded methods so do not get confuse withm1
andm2
.. they are just to differentiate in this example... they both have same signature). But at compile time, all java compiler does is goes to the reference type (ClassA
in this case) checks the method if it is present and expects the programmer to handle it. So obviously, you will throw or catchE1
. Now, at runtime, if the overloaded method throwsE2
, which isE1
's superclass, then ... well, it's very wrong (for the same reason we cannot sayB myBObj = new A()
). Hence, Java does not allow it. Unchecked exceptions thrown by the overloaded method must be same, subclasses, or non-existent.The overriding method must NOT throw checked exceptions that are new or broader than those declared by the overridden method.
Example: