1

我正在准备自己的测试,我发现这段代码我看不懂。

如果我像这样重写一个方法,它就无法编译。好,可以。我必须在第 2 行抛出父异常(如 throws Exception),它会正常工作......但是,为什么有可能用 public void charlie throws NullPointerException 更改第 7 行?这会编译得很好,因为我仍然没有在第 2 行扔任何东西。

    1.public class A {
    2.  public void charlie() 
    3.  {
    4. 
    5.  }
    6.  class B extends A{
    7.      public void charlie() throws IOException
    8.      {}
    9.  }
    10.}
4

3 回答 3

8

NullPointerException是一个未经检查的异常(因为它 extends RuntimeException)。它永远不需要声明,并且可以在不影响其他任何内容的情况下进行声明。

您应该修改对已检查和未检查异常的理解。

Java 异常教程可能是一个合理的起点。

于 2013-05-08T19:55:12.273 回答
1

答案很简单:如果 A 类中的原始方法不“支持”抛出异常,则不能在 B 类中的覆盖方法中抛出异常。

假设您将从其他地方调用您的方法:

A a = new A();
a.charlie();

由于charlie类中的方法A确实会引发任何异常,所以没关系。如果该方法会引发异常,则必须编写

A a = new A();
try {
    a();
} catch(IOException ex) { //or any other exception
    //oh noes
}

但是现在它变得复杂了,因为一种叫做类多态的东西会让你的工作模式变得复杂:

private A getA() {
    return new B(); //this will work since B extends A
}

private void doSomething() {
    A a = new A(); //you could also write A a = new B();
    a.charlie();
}

现在这段代码接受a了来自类的对象,A并且它有charlie()没有抛出异常的方法。即使a是来自 class 的对象B,编译器也不知道它,也不查看在 class 的方法中抛出了哪些异常B,因为a来自 class A,至少从编译器的角度来看是这样。

这就是为什么类中的方法必须与charlie()类中的方法相同(输入参数、返回类型和抛出的异常) ,您只能更改方法的主体。BA

但是,您仍然可以抛出 NullPointerException 或 UnsuportedOperationException,因为它们属于 RuntimeException,并且 Java 中的每个现有方法都会自动抛出 RuntimeException,因此您可以随时抛出任何这些。

于 2013-05-08T20:17:32.140 回答
0

IOException是必须捕获的异常;你不能调用一个throws没有try-catch块的方法。

但是,现在考虑以下几点:

A myObject;
myObject = new B(); // legal - polymorphism
myObject.charlie();

人们可能期望这不会引发错误,因为A没有throws声明,但B确实有。因此,此代码不能合法。

一个方法可能声明的抛出的异常更少,但不会更多

于 2013-05-08T19:56:13.117 回答