16

这是我的代码块。

class Alpha{
    public void Gamma() {
        System.out.println("Alphas");
    }
}

class Beta extends Alpha{
    public void Gamma() throws Exception //Line 1
    {
        try {
            System.out.println("Betas");
        } catch(Exception e) {
            System.out.println("Exception caught");
        } finally {
            System.out.println("xfg");
        }
    }
    public static void main(String[] args) throws Exception {
        Alpha g = new Beta();
        g.Gamma();
    }
}

此代码无法编译,因为我在 Line1 中添加了“throws”。

编译器抱怨被覆盖的方法不能抛出异常。

为什么这样 ?。

为什么不能被覆盖的方法抛出异常?

因为我可以通过在子类实现中添加 n 行代码来覆盖基类中的方法。

这些添加的代码可能会引发异常,所以为什么我不能在覆盖的方法中使用“抛出”?

4

6 回答 6

31

被覆盖的方法可以抛出异常,只要被覆盖的方法也抛出相同的异常。你不能引入新的例外。

那么为什么不能引入一个新的异常呢?

OOP 的核心概念之一是使用抽象类型,并且所有子类型都可以被视为抽象类型。参见Liskov 替换原则

您不能引入更广泛行为的原因是,如果来自抽象类型(超类或接口)的方法没有抛出异常并且您将对象称为该类型,您会得到意想不到的行为:

Alpha alpha = new Beta();
// At this point, the compiler knows only that we have an Alpha
alpha.myMethod();

如果 AlphamyMethod()没有抛出异常,但 Beta,我们可能会在上面的代码中得到一个意外的异常。

于 2013-08-25T05:41:27.930 回答
7

子类覆盖的方法/方法只能抛出(声明)未经检查的异常,如 ArrayIndexOutOfBoundsException。

但是您不能抛出(声明)已检查的异常。像 IOException。

覆盖方法抛出异常的示例 Java

class A{
 public void show(){
   // some code here
  }
}

class B extends A{
public void show() throws ArrayIndexOutOfBoundsException{
   // some code here
  }
}

希望这些可以帮助你。

于 2014-05-14T14:59:10.720 回答
4

您的客户端总是考虑处理基本版本。这就是多态性的全部好处 => 客户端忽略了覆盖的。

因此,没有什么会迫使客户端处理被覆盖的特定规则,这里是被覆盖方法抛出的潜在异常的情况。

这就是为什么被覆盖的方法不能抛出更广泛的异常。它会破坏合同。

因此,关于这个逻辑,规则是: 重写方法 CAN(如果需要)只抛出基本版本中声明的异常的子部分,但不能抛出更广泛的异常。

于 2013-08-25T05:41:10.573 回答
1

规则说

“子类重写方法不能抛出比超类方法更多的异常”。

于 2013-08-25T05:39:07.273 回答
1

编译器抱怨被覆盖的方法不能抛出异常

不,它没有。再次阅读该消息。它说您不能抛出未声明为被覆盖方法抛出的异常。根本不是一回事。

于 2013-08-25T06:05:50.053 回答
0

您在 main 方法中的上述代码

阿尔法 g = 新贝塔();// 现在它创建了一个新的Beta类的实际对象,引用为Alpha

g.伽玛();// * 现在编译器只查看 Alpha 类中存在的 Gamma() 方法,默认情况下它也通过继承存在于 Beta 类中。但是编译器只查看类 Alpha 并提出问题是包含方法 Gamma() 并找到了答案是的。

假设当 java 编译器允许在Beta 类的 gamma() 方法中抛出更多检查异常时,会发生什么情况

  • 现在在编译时编译器只依赖于 Alpha 类的 Gamma() 方法。它不会强制处理这个异常或抛出这个错误的异常,因为它可能会抛出(假设 java 编译器允许在覆盖的方法中抛出更多检查的异常)。但实际上编译器并没有限制抛出异常,还限制了可访问性修饰符。

    因为非静态方法调用发生在实际对象方法上而不是类型上,我们赋予任何超类型,并且在编译时编译器仅检查该类型分配的类中的可访问性和存在性。

所以我认为这就是这个被覆盖的合同背后的原因

• 方法定义不能缩小方法的可访问性,但可以扩大它。• 方法定义只能抛出所有或无,或在超类中被覆盖方法的 throws 子句中指定的检查异常的子集(包括它们的子类)。

于 2013-10-18T09:59:21.720 回答