这是我的代码块。
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行代码来覆盖基类中的方法。
这些添加的代码可以抛出一个异常,为什么我不能在重写方法中使用“throws”?。
答案 0 :(得分:19)
重写的方法可以抛出异常,只要重写的方法也会抛出相同的异常。您不能介绍新的例外。
那你为什么不能引入一个新的例外?
OOP的一个核心概念是使用抽象类型,并且所有子类型都可以被视为抽象类型。见Liskov Substitution Principle
您无法引入更广泛行为的原因是,如果抽象类型(超类或接口)中的方法不会抛出异常并且您将对象称为该类型,则会出现意外行为:
Alpha alpha = new Beta();
// At this point, the compiler knows only that we have an Alpha
alpha.myMethod();
如果Alpha的myMethod()
没有抛出异常,但Beta的会抛出,我们可能会在上面的代码中遇到意外的异常。
答案 1 :(得分:6)
子类覆盖方法只能像ArrayIndexOutOfBoundsException一样抛出(Declare)unchecked exception。
但是您不能抛出(声明)已检查的异常。像IOException。
verriden方法的示例抛出异常Java
class A{
public void show(){
// some code here
}
}
class B extends A{
public void show() throws ArrayIndexOutOfBoundsException{
// some code here
}
}
希望这些可以帮到你。
答案 2 :(得分:3)
您的客户端总是考虑处理基本版本。这是多态性的全部好处=>客户端忽略了覆盖的一个。
因此,没有任何东西会强制客户端处理覆盖所产生的特定规则,这里是覆盖方法抛出的潜在异常的情况。
这就是为什么覆盖方法不能抛出更广泛的异常。这会违反合同。
因此,关于这个逻辑,规则是: Overriden方法CAN(如果需要)只抛出在基本版本中声明的异常的子部分但是不能抛出更广泛的部分。
答案 3 :(得分:1)
规则说
“子类重写方法不能抛出更多异常 超类方法“。
答案 4 :(得分:1)
编译器抱怨重写的方法不能抛出异常
不,不。再次阅读该消息。它表示你不能抛出一个未被声明被重写方法抛出的异常。根本不是一回事。
答案 5 :(得分:0)
主要方法
中的上述代码Alpha g = new Beta(); //现在它创建一个新的 Beta 类的实际对象,引用 Alpha
g.Gamma(); // *现在编译器看起来只有Gamma()方法呈现在Alpha类关闭cource它在Beta类中也默认通过继承。但编译器只查看类Alpha并问一个问题是包含一个方法Gamma()并找到答案是的,它有。
假设java编译器提供了在 Beta类中的gamma()方法中抛出更多已检查异常的条件,那么将会发生什么
现在在编译时编译器只依赖于类Alpha的Gamma()方法。它不会强制处理这个异常或抛出这个错误,因为它可能会抛出(假设java编译器允许抛出更多的重写方法中的异常)。 但实际上编译器不会限制抛出异常,也会限制可访问性修饰符。
因为非静态方法调用发生在实际的对象方法而不是类型上,我们给任何超类型,并且在编译时编译器只检查该类型的已分配类的可访问性和存在。
所以我认为这就是这个被覆盖的合同背后的原因
•方法定义不能缩小方法的可访问性,但它 可以扩大它。 •方法定义只能抛出全部或全部,或者是子集 检查了throws中指定的异常(包括它们的子类) 超类中重写方法的子句。