继承,方法签名,方法重载和throws子句

问题描述:

Parent类是:继承,方法签名,方法重载和throws子句

import java.io.IOException; 
public class Parent { 
     int x = 0; 
     public int getX() throws IOException{ 
     if(x<=0){ 
     throw new IOException(); 
     } 
     return x; 
     } 
} 

extend这个类写一个子类Child

public class Child1 extends Parent{ 
    public int getX(){ 
     return x+10; 
    } 
} 

通知而覆盖的getX方法在Child类中,我已经从方法定义中删除了throws子句。现在它结果在由编译器的异常行为预计:

new Parent().getX() ; 

不编译而无需在try-catch块包围它,如所预期。

new Child().getX() ; 

编译时没有将其封装在try-catch块中。

但是下面的代码行需要try-catch块。

Parent p = new Child(); 
p.getX(); 

由于这可能也就是使用一个父类引用调用运行时多态性期间孩子的方法可以预见,为什么的Java的设计者并没有强制要求包括在方法定义,而throws子句覆盖特定的父类方法?我的意思是,如果一个父类方法在其定义中引发了子句,那么在覆盖它的时候,重写方法也应该包含throws子句,不是吗?

+0

在你最后一句话中,你的意思是“,然后重写它的***重写***方法(子类中的方法)还应该包括throws子句”??? – Bhushan 2012-01-27 16:11:42

不,这是适当的 - 重写的方法可能会对它抛出(并返回)的内容产生更多限制,因为这对编译时知道的调用者有用,它们将使用重写的方法,并且不想打扰无法发生的例外情况等等。但它必须更具限制性,而不是更多允许虽然如此,所以它不能让惊喜的呼叫者通过父声明来访问

通过类型Parent的引用使用重写的方法永远不会违反“它可能抛出IOException”的合同 - 没有例外不违反合同。反过来说(如果父母没有声明异常,但覆盖的方法确实会)违反合同。

+0

感谢您的启发:) – NINCOMPOOP 2012-01-27 16:08:02

+0

你可以接受乔恩的答案然后:) – Bhushan 2012-01-27 16:12:47

+0

'这样就不会惊讶呼叫者通过父声明来访问它。这真的帮助我理解了推理。 – 2014-09-22 15:55:53

那么,重写方法可能不会抛出任何异常(或至少更少的异常),因此您可以从throw子句(或整个throw子句)中移除异常。

假设覆盖方法捕获所有异常,记录它们并返回一个特殊值。虽然这不是很好的风格(它会改变方法的语义),但它仍然是可能的,因此如果你在编译时知道你正在处理一个Child,你就不必捕获从不抛出的异常。

添加例外将不起作用,因为通过Parent引用访问该类的用户不知道Child可能添加的任何异常。

你可以自由地覆盖一个方法没有抛出关键字,因为如果你想开发通过控制所有的异常的方法,那么你可以做到这一点通过重写的方法,没有throws子句。

但记住一件事,如果你想在子类方法中包含throws子句,那么throws子句必须与异常相关联,该异常必须是相同的异常,或者由其超类方法引发的异常的子类。用于示例 -

class Super{ 
    void a()throws IOException{ 
     ...... 
    } 
} 
class Sub extends Super{ 
    void a()throws IOException{ 
     ...... 
    } 
} 

的一个()类亚方法必须抛出IOException或IOException的任何亚类,否则编译器将显示错误。

,如果你写

void a()throws Exception 
在类子

这意味着,然后它会导致编译错误。

易记

  1. 访问修饰符可以从限制改为限制较少,
    例如,从保护公众,但不是反之亦然
  2. 抛出签名可以从父异常改变孩子异常类,但不反之亦然

此代码是有效的

public class A { 

    protected String foo() throws Exception{ 
     return "a"; 
    } 

    class B extends A { 
     @Override 
     public String foo() throws IOException{ 
      return "b"; 
     } 
    } 
} 

Overrided foo的方法有公共接入,不受保护,抛出IOException异常异常的那个孩子

此代码无效

public class A { 

    public String foo() throws IOException{ 
     return "a"; 
    } 

    class B extends A { 
     @Override 
     protected String foo() throws Exception{ 
      return "b"; 
     } 
    } 
} 

Overrided foo的方法具有更多的限制访问修饰符,并抛出异常,不是孩子IOException异常

通过您可以覆盖从超类方法,并在所有

这个C不会抛出ecxeptions方式有效的

public class A { 

    public String foo() throws IOException{ 
     return "a"; 
    } 

    class B extends A { 
     @Override 
     public String foo(){ 
      return "b"; 
     } 
    } 
} 
+0

这有助于在面试中因此问题而遭到破坏。 – saiki4116 2015-11-14 22:47:25