这是我的代码块。
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();
}
}
这段代码编译失败,因为我在第1行中添加了"throws"。
编译器抱怨被重写的方法不能引发异常。
为什么?。
为什么重写的方法不能抛出异常?。
因为我可以通过在子类实现中添加n行代码来覆盖基类中的方法。
这些添加的代码可以引发异常,那么为什么我不能在重写的方法中使用"throws"呢?。
被重写的方法可以抛出Exceptions,只要被覆盖的方法也抛出相同的Exceptions。您不能引入新的异常。
那么,为什么不能引入一个新的Exception呢?
OOP的核心概念之一是使用抽象类型,并且所有子类型都可以被视为抽象类型。参见利斯科夫替代原理
你不能引入更广泛的行为的原因是,如果抽象类型(超类或接口)的方法没有抛出Exception,并且你将对象称为该类型,那么你会得到意想不到的行为:
Alpha alpha = new Beta();
// At this point, the compiler knows only that we have an Alpha
alpha.myMethod();
如果Alpha的myMethod()
没有抛出异常,但Beta的抛出了,那么我们可能会在上面的代码中得到一个意外的异常。
子类覆盖方法只能抛出(Declare)未检查的异常,如ArrayIndexOutOfBoundsException。
但是您不能抛出(声明)已检查的异常。如IOException。
重写方法抛出异常的示例Java
class A{
public void show(){
// some code here
}
}
class B extends A{
public void show() throws ArrayIndexOutOfBoundsException{
// some code here
}
}
希望这些能对你有所帮助。
您的客户端总是考虑处理基本版本。这就是多态性的全部好处=>客户端忽略了被覆盖的一个。
因此,没有什么会迫使客户端处理overriden制定的特定规则,这里是overriden方法引发的潜在异常的情况。
这就是为什么overriden方法不能抛出更广泛的异常的原因。这将违反合同。
因此,关于这个逻辑,规则是:Overriden方法可以(如果它愿意的话)只抛出基础版本中声明的异常的一个子部分,但不能抛出更广泛的异常
规则说
"子类重写的方法不能引发比超类方法"。
编译器抱怨被重写的方法不能抛出异常
不,没有。请重新阅读邮件。它表示不能抛出未声明由重写方法抛出的异常。一点也不一样。
您在主方法中的上述代码
Alpha g=新Beta();//现在它创建了一个Beta类的新的实际对象,引用了Alpha
g.伽马();//*现在编译器只看Gamma()方法出现在Alpha类中,默认情况下它也通过继承出现在Beta类中。但是编译器只看了Alpha类并问了一个问题。它包含一个方法Gamma(。
假设一个条件,当java编译器提供了在Beta类中的gamma()方法中抛出更多已检查异常的便利,那么会发生什么
-
现在在编译时,编译器只依赖于类Alpha.it的Gamma()方法。它不强制处理此异常或抛出此异常,这是错误的,因为它可能会抛出(假设java编译器允许在重写方法中抛出更多已检查的异常)。但实际上编译器并没有对抛出异常进行限制,而是对可访问性修饰符进行了限制。
因为非静态方法调用发生在实际的对象方法上,而不是类型上,并且我们赋予任何超类型,并且在编译时编译器只检查该类型的已分配类中的可访问性和存在性。
所以我认为这就是合同被推翻的原因
•方法定义不能缩小方法的可访问性,但它可以拓宽它。•方法定义只能抛出全部或全部,或throws中指定的已检查异常(包括其子类)子句。