看看这段代码:
public interface Foo {
public void bar() throws Exception;
}
public class FooImpl implements Foo {
public void bar() {
}
public static void main(String args[]) {
Foo foo = new FooImpl();
foo.bar();
}
为什么我会得到一个"未处理的异常类型"编译错误,而如果我改变了
Foo foo = new FooImpl();
到
FooImpl foo = new FooImpl();
我不会收到任何错误?
根据我的理解,公共方法使用动态绑定,所以不应该使用原始代码调用FooImpl的bar()方法吗?
答案 0 :(得分:3)
printf
抛出一个已检查的异常;尽管覆盖Foo#bar
,但FooImpl#bar
却没有。在确定您的代码是否需要捕获异常时,bar
会考虑静态类型。
答案 1 :(得分:1)
关键是你可以减少从你覆盖的方法抛出的异常列表(在接口的情况下实现)。这并不违反班级合同。
现在,当您使用对接口的引用时,编译器会看到调用的方法被声明为抛出异常,因此您必须处理它。
但是,如果您使用对实现类的引用,编译器会发现您已经减少了实现/重写方法的异常列表,因为您的实现根本不会抛出该异常,因此没有必要强迫您处理从未抛出的东西。
答案 2 :(得分:0)
您已声明Foo::bar
可能会抛出已检查的异常,因此如果您的变量声明为Foo
类型,那么您必须处理异常的可能性。
您已声明FooImpl::bar
不会抛出已检查的异常,因此如果您的变量声明为FooImpl
类型,则您不必处理异常的可能性。
多态性的一点是,如果你的变量的类型为Foo
,那么调用bar
的代码就不知道它所获得的方法的实现方式;它只知道Foo
声明的方法。