10
votes

Consider following classes:

class X
{
public void met()
   {
   }
}

and

class Y extends X
{
    public void met() throws NullPointerException
    {
        throw new NullPointerException();
    }
}

From what I have read on other questions ( Why can't overriding methods throw exceptions broader than the overridden method? and Java method throwing exception )

I understand that the overriding method in the subclass, has to throw either the same or a subclass of the exception thrown in the overridden method.

Do Java methods always throw at least an exception of the type Exception?

...In other words the compiler adds throws Exception

So the class X would look like this

class X {
    public void met() throws Exception {

    }
}

I want to clarify that I am not mistaken about the fact that the default exception handler Exception is always added.

Related questions:

IOException vs RuntimeException Java

2
Nope. It doesn't. Note that unless you have a specific reason to propagate exceptions up the caller hierarchy (by throwing them), you should probably handle them using catch blocks (or try-with-resources)TheLostMind
NullPointerException is a RuntimeException and doesn't need a throws clause.Mark Rotteveel
The only type of exception that does not need to be declared is RuntimeException and the exceptions that extend it.EpicPandaForce
Ok, why is it that the compiler doesn't complain when I override the met method? In the super's method I do not throw any exceptions. The signature has changed in subclass.Anthony H
First of all a class cant throw exception.Kartic

2 Answers

9
votes

There are two types of Exceptions: checked Exceptions (like ParseExceptionwhen parsing text) and unchecked Exceptions (like NullPointerException).

Checked Exceptions must be declared in the method signature. Unchecked Exceptions may be declared in the method signature.

When overriding methods (from an interface or a super class) you only have to specify the exceptions, that you are throwing in your implementation. You cannot declare to throw checked exceptions in an implementation that are not allowed in the overridden method.

This is allowed:

class X { void someMethod() }
class Y extends X { @Override void someMethod() throws UncheckedException }

This is not allowed:

class X { void someMethod() }
class Y extends X { @Override void someMethod() throws CheckedException }

This is also allowed:

class X { void someMethod() throws CheckedException }
class Y extends X { @Override void someMethod() }
3
votes

What slartidan said in their answer is fully correct. To explain a little more:

If you are throwing a "Checked Exception" inside the body of a method, you are required to either handle it (using a catch-block) or to declare a throws-clause

To reiterate the previously linked JLS:

  1. An Exception is a class extending Throwable
  2. An Error also is a class extending Throwable
    • Errors usually should not be caught, because they indicate serious problems. (e.g. OutOfMemoryError)
    • catching Exception does not catch Errors
  3. There also is RuntimeException. This is a class extending Exception

Errors and Runtime Exceptions are not checked at compile time, because that exactly is what "checked exception" means.

You may throw Errors and RuntimeExceptions anywhere in your code.

Now how does this affect throws clauses:

A throws clause specifies that an invocation of the declared method may result in the exception specified. Interestingly throws expects a Throwable, which makes following declaration valid:

public void method() throws StackOverflowError, NullPointerException {
    //...
}

There is no compiler effect when declaring non-checked Exceptions in a throws clause, but it's sometimes done for additional clarity in your sourcecode.

Additionally such Exceptions are sometimes mentioned in JavaDoc (e.g. BigInteger#divide)

But the compiler checks the throws clause when overriding methods. It's somewhat similar to the visibility rules when overriding methods. This means throwing unchecked Exceptions (and declaring corresponding throws clauses) can always be done. Following declaration is valid:

public interface Demo {
    void test();
}
public class DemoImpl implements Demo {
    public void test() throws NullPointerException {
        throw new NullPointerException();
    }
}

It's the same the other way round. Unchecked exceptions in throws clauses are disregarded by the compiler, because they aren't relevant to compile-time checking:

public interface Demo {
    void test() throws NullPointerException;
}
public class DemoImpl implements Demo {
    public void test() {
        throw new NullPointerException();
    }
}

The general rule for throws-clause inheritance is: One interface to rule them all: The interface must declare all checked exceptions that can be thrown by implementing classes. Or in other words:

Implementing classes may declare a subset of the declared checked Exceptions in the interface method's throws-clause in the throws-clause of the implementing method

This means following is valid:

public interface Demo {
    void test() throws IOException, ParseException;
}
public class DemoImpl implements Demo {
    public void test() throws IOException {
        throw new IOException();
    }
}

What's not valid is declaring a checked exception in the implementing method's throws-clause that's not declared in the corresponding interface method's clause:

public interface Fail {
    void test() throws ParseException;
}
public class FailImpl implements Fail {
    public void test() throws IOException {
        throw new IOException();
    }
}