public class A {
void foo() throws Exception {
throw new Exception();
}
}
public class SubB2 extends A{
void foo(){
System.out.println("B");
}
}
public class Tester {
public static void main(String[] args) {
A a=new SubB2();
a.foo();
}
}
执行结果是:
A、B
B、B,然后异常
C、由于第9行上的错误,导致编译失败
D、由于第16行上的错误,导致编译失败
E、只有异常
答案是:D
解析
亲测结果如下
本来Sub2应该继承父类throws异常的,但实际上,当你编译这段代码时,编译器并没有报错,是因为编译器在编译时主要关注语法和明显的类型错误。
在这种情况下,SubB2类的foo方法确实覆盖了父类的foo方法,且没有引入新的语法错误,所以编译可以通过。
但当运行到a.foo();时,问题就出现了。Java运行时环境会检查方法的签名,包括返回类型和抛出的异常,以确保它们在运行时是兼容的。在这个例子中,运行时环境发现SubB2的foo方法没有声明抛出异常,但是实际执行的方法(来自父类A)确实抛出了异常。这就是为什么在运行时会抛出异常的原因。
(总结)简单来说,编译器在编译时可能没有发现这个问题,但是运行时环境会检查得更详细,并在这个情况下抛出异常。这就是为什么你在运行a.foo();时才看到异常的原因。