Reputation: 199
After reading Why can't overriding methods throw exceptions, I understand that if method declared as throws a Checked exception, the overriding method in a subclass can only declare to throw that exception or its subclass:
class A {
public void foo() throws IOException {..}
}
class B extends A {
@Override
public void foo() throws SocketException {..} // allowed
@Override
public void foo() throws SQLException {..} // NOT allowed
}
So because SocketException
IS-A IOException
I can declare the overriding method as throws any of subclass of IOException
.
In my program, I want to invoke the overriding method declared as throws FileNotFoundException
IS-A IOException
. also handled with a try-catch block
import java.io.*;
class Sub extends Super{
public static void main (String [] args){
Super p = new Sub();
try {
p.doStuff();
}catch(FileNotFoundException e){
}
}
public void doStuff() throws FileNotFoundException{}
}
class Super{
public void doStuff() throws IOException{}
}
But I am getting that compile-time error:
Sub.java:6: error: unreported exception IOException; must be caught or declared to be thrown
p.doStuff();
^
What is the reason for that? I'm a little confused because everything that the Base class has also available to the subclasses.
Also much more confusing is the ability to catch Exception
and Throwable
In addition to IOException
(The opposite from Overriding concept).
Upvotes: 13
Views: 2287
Reputation: 7267
Your object reference is of type Super
, even though you know it's a Sub
object at runtime. Therefore the compiler is checking the method definition of the Super
and giving you this compile error.
It would be no different from getting the following compiler error:
Object o = new String("Hello World");
o.charAt(2); //Obviously not allowed
It's important to remember that the throws
clause is part of the method definition.
Upvotes: 14
Reputation: 15212
What is the reason for that? I'm a little confused because everything that the Base class has also available to the subclasses.
You need to catch an IOException
and not a FilenotFoundException
. This is because of the fact that while the doStuff
method from the subclass will be called at runtime, the compiler doesn't know about this yet. It only knows about the doStuff
method in the super class which declares that it throws
an IOException
.
To address your edit : The catch
block can chose to catch the exact exception that is expected in the try
block or it can chose to catch a superclass of the exception. The reasoning behind this has got nothing remotely to do with method overriding.
Upvotes: 11
Reputation: 512
By declaring p as Super
Super p = ...
your Compiler only knows p
is some kind of Super
. Super
's doStuff()
throws an IOException
, but your code catches only a special case of IOException
, the FileNotFoundException
. If you want to tell your Compiler this is definetly a Sub
and not a Super
just declare p
as Sub
.
In this case it's explicit not declared as Sub
but as Super
so any Super
or its Childs might occur and throw any IOException
which might not be a FileNotFoundException
or any of it's childs.
Upvotes: 3
Reputation: 533570
The compiler doesn't consider the type of the object, but the type of reference you are using which is Super
.
As Super.doStuff() throws IOException
, this is what you must catch.
BTW I highly recommend using an IDE, you will find it more productive.
Upvotes: 5
Reputation: 720
Because it makes checks by declared type, in this case Super
.
It is not known (or checked) that your p
will contain only instances of Sub
. Also, it would not make sense to define a superclass variable and use it only and only for 1 particular subclass.
So your Super p
contains instance of a Super.class
. Its method doStuff()
can throw everything that extends IOException
, lets say UnsupportedEncodingException
, but you try-catch only for FileNotFoundException
, so that Unsupported...
may have been thrown and must be handled.
Upvotes: 2
Reputation: 906
That's because you are using an object of static type Super. The compiler can not know that at runtime p is pointing to a Sub object, so it wants to catch the exceptions thrown by the method declared in the Super class
Upvotes: 2