简体   繁体   中英

Interface Declaration with Unchecked vs. Checked Exceptions

I've searched for a potential answer to my question below, and have not found one.

I understand the difference between checked and unchecked exceptions as well as what the programmer can/must do with them. However, I don't quite understand how the compiler interprets unchecked exceptions when it comes to interfaces.

Recently, I was programming an interface and implementation similar to the following:

public interface Operation {
    int operate(int x, int y) throws ArithmeticException;
}

public class Divide implements Operation {
    @Override
    public int operate(int x, int y) throws ArithmeticException {
        try {
            return x / y;
        } catch (ArithmeticException ex) {
            System.out.println("Division error!");
        }
    }
}

Here's where I'm confused. The following implementation will also compile:

public class Divide implements Operation {
    @Override
    public int operate(int x, int y) {
        return x / y;
    }
}

Why does the compiler not care that I have declared the method as throwing an exception in the interface? I understand that Unchecked Exceptions are Runtime Exceptions and that it is not required that the programmer handle them, but do not understand why when I explicitly state in my interface that I want the exception handled that it does not force me to handle it.

Could someone lend an explanation as to why the compiler will allow this situation to occur?

You're confusing "handling" an exception with inheritance rules. When you implement or override a method, there is no rule that says the new method must throw exactly the same exceptions that the implemented/overridden method does. The only rule is that it cannot throw a checked exception that is outside the range of allowable exceptions for the parent method. Think of the interface as establishing a contract with the outside world. It says, "anybody who calls this method must be prepared to handle these types of exception". Implementors are then free to throw the exception, knowing that it will be handled, but they're by no means required to throw it.

In addition to the previous answers, its worth to note that this code is perfectly ok for checked exceptions:

interface Translator {
    String translate(String s) throws IOException; /* <-- Checked exception */
}

class EnglishGermanTranslator implements Translator {
    @Override
    public String translate(String s) {  // <-- no exception, but its ok
        return ""; // logic is irrelevant...
    }
}

public class Test {
    public static void main(String[] args) {
        EnglishGermanTranslator t = new EnglishGermanTranslator();
        t.translate("Text to translate");  // No problems...
    }
}

But when we refer to the EnglishGermanTranslator via Translator , we have to catch an appropriate exception:

public class Test {
    public static void main(String[] args) {
        Translator t = new EnglishGermanTranslator();
        t.translate("Text to translate");  // <-- compilation error... try-catch required  (or throws in main)
    }
}

Declaring runtime exceptions in the throws clause is only for the sake of information (and javadoc) - so that the users of your class/interface know what to expect in a given situation.

Since they are runtime, the compiler does not enforce anything about them - neither catching, nor declaring.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM