Why Can't Overriding Methods Throw Exceptions Broader Than the Overridden Method

Why can't overriding methods throw exceptions broader than the overridden method?

It means that if a method declares to throw a given exception, the overriding method in a subclass can only declare to throw that exception or its subclass. For example:

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
}

SocketException extends IOException, but SQLException does not.

This is because of polymorphism:

A a = new B();
try {
a.foo();
} catch (IOException ex) {
// forced to catch this by the compiler
}

If B had decided to throw SQLException, then the compiler could not force you to catch it, because you are referring to the instance of B by its superclass - A. On the other hand, any subclass of IOException will be handled by clauses (catch or throws) that handle IOException

The rule that you need to be able to refer to objects by their superclass is the Liskov Substitution Principle.

Since unchecked exceptions can be thrown anywhere then they are not subject to this rule. You can add an unchecked exception to the throws clause as a form of documentation if you want, but the compiler doesn't enforce anything about it.

Overridden methods cannot throw exceptions Java

Overridden methods can throw Exceptions, so long as the method being overridden also throws the same Exceptions. You can't introduce new Exceptions.

So why can't you introduce a new Exception?

One of the central concepts of OOP is using abstract types, and that all subtypes may be treated as the abstract type. See Liskov Substitution Principle

The reason you can't introduce broader behaviour is that if the method from the abstract type (super class or interface) doesn't throw an Exception and you refer to your object as that type, you'd get unexpected behaviour:

Alpha alpha = new Beta();
// At this point, the compiler knows only that we have an Alpha
alpha.myMethod();

If Alpha's myMethod() doesn't throw an Exception, but Beta's does, we could get an unexpected Exception in the above code.

Why can overriding methods throw any unchecked exception?

why overriding methods can throw unchecked exception in java ?

Any method in Java can throw an unchecked exception. An overriding method is also a method so it gets the same privileges as other methods when it comes to unchecked exceptions.

I just want to know why Overriding methods CAN throw unchecked
exception while cannot throw checked exception

The last part of your sentence is incorrect. An overriding method can throw both checked an unchecked exceptions. I believe the questions that you are trying to ask are

  1. Why CAN'T an overriding method throw a checked exception when the overriden method doesn't.
  2. Why CAN an overriding method throw an unchecked exception when the overriden method doesn't.

Let's answer 1)

   class Parent {
public void doSomething() { }
}

class Child extends Parent {
public void doSomething()throws Exception { }
}

Let's assume that the above code was allowed. The client code would then look like this :

   Parent p = new Child();
p.doSomething();

If there was no restriction on what checked exceptions could be thrown by an overriden method, there would be no compilation error in the above code. The compiler has no idea that doSomething in Child can actually throw a checked Exception. The throw Exception clause for the doSomething method in Child would kind of be pointless since the programmer is not required to handle the checked exception.

Let's answer 2)

The Oracle tutorial has a nice write-up that is useful in the context of your question :

Runtime exceptions represent problems that are the result of a
programming problem, and as such, the API client code cannot
reasonably be expected to recover from them or to handle them in any
way. Such problems include arithmetic exceptions, such as dividing by
zero; pointer exceptions, such as trying to access an object through a
null reference; and indexing exceptions, such as attempting to access
an array element through an index that is too large or too small.

Runtime exceptions can occur anywhere in a program, and in a typical
one they can be very numerous. Having to add runtime exceptions in
every method declaration would reduce a program's clarity. Thus, the
compiler does not require that you catch or specify runtime exceptions
(although you can).

Since the programmer is not obliged to catch a RuntimeException that is thrown by a method, putting the same restriction as checked exceptions for unchecked exceptions in case of overriden methods would be pointless.

Exception in overriding methods

Overridden methods cannot throw newer or broader checked exception just because, when the object of this class is referred polymorphic-ally, the caller can handle only exceptions shown in the contract by the base class method implementation.

Overridden method can throw unchecked exception in case if parent method throws it or not. You can even not declare it in signature.
But if parent method throws checked exception you can only specialize this exception in the child (throw same exception, it's descendants or none).

Refer this link for better understanding : http://www.javatpoint.com/exception-handling-with-method-overriding

Invoking overriding method that throws Checked exception

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.

Overriding Method with Exception

You can declare an overriding method as throwing less types of exceptions than the superclass, you just can't introduce new ones. The subclass method has to be compatible with the behavior of the superclass method. More exactly, you have to be able to substitute objects of the subclass for objects of the superclass without breaking anything (where adding a new checked exception to the throws clause would mean things calling it would have to change their code to handle it).

(The idea behind this is the Liskov Substitution Principle: a program should be able to deal with objects at a high level without getting bogged down in details about everything's exact type. If subclasses can introduce changes that mean the program has to pick them out and handle them differently then it defeats the purpose of abstraction.)

So an overriding method can be declared as throwing no checked exceptions at all (by omitting the throws clause entirely), because that doesn't require changes to any callers.

There are examples in the JDK, such as in java.io, where the subclass can't possibly throw an exception declared by the super class (see the ByteArrayOutputStream close method). Here the close method could have had its throws clause removed, since it never throws IOException. (Maybe it was left on the chance someone would want to subclass it with a version that did throw IOException?)



Related Topics



Leave a reply



Submit