1

考虑一个 Java 类层次结构,例如:

abstract class Exp { public void generate(); }
class EffExp extends Exp {...}
clas PureExp extends Exp {...}
class NewExp extends EffExp {...}
etc, etc.

generateinside的实现NewExp被更改为抛出一个IOException.

public void generate() throws IOException {...}

其他实现generate不做任何 IO 因此不需要抛出它。编译器抱怨并强迫我声明类层次结构中的所有方法以引发异常。这真的是唯一的出路吗?这似乎相当侵入。

我当然可以捕捉到它发生的异常, inside NewExp,但这并没有什么意义。异常应该传播到顶部并停止程序执行。

这里更一般的问题是:如果您有一个相互覆盖的方法层次结构,是否都必须声明它们以抛出相同的异常集?

4

7 回答 7

1

只要记住一条规则:-

  • 您无法对您覆盖的方法添加更多限制。限制可以是例如: - 添加一个新的Checked Exception,降低方法的可见性。

所以,如果你必须(别无选择),让你的覆盖方法抛出一个Checked Exception(注意,你可以添加一个未经检查的异常,但它没有任何意义),只需在 throws 子句中添加异常您正在覆盖的方法。

因此,简单来说,您的overridden方法的签名应该与覆盖它的签名完全匹配。


现在这背后的简单推理是 - Polymorphism

如您所知,在多态中,您可以拥有super type指向子类对象的引用点。所以,你可以有: -

SupClass ref = new SubClass();
ref.method1();

现在,在检查 是否存在时method1,编译器只关心引用类型。因此,它签入SupClass,并相应地允许访问。

现在,想象一下会发生什么,在运行时,当ref实际指向SubClass对象时,JVM 发现method1抛出了一个新的异常,而compiler. 它会崩溃。这就是为什么它是不允许的。

于 2012-12-17T11:43:44.797 回答
1

假设场景是这样的:

abstract class Exp { public void generate(); }
class EffExp extends Exp { public void generate throw IOException(....)....}
clas PureExp extends Exp {public void generate(....)....}

我们使用抽象类表示法,以便我们可以实现我们的其他类而不用担心实际的实现。如果我们做实际;实现范围缩小了,即在某些情况下抛出异常,在其他情况下不抛出异常,那么它显然违反了 Java 的健壮性。所以你需要清楚地同步。对于所有方法。

尽管您可以通过抛出父级“异常”来增加可见性。

于 2012-12-17T11:53:47.937 回答
1

在抽象类中,您可以定义抛出 java.lang.Exception

abstract class Exp { public abstract void generate() throws Exception; }

在派生类中更具体地说明您抛出的异常类型。

于 2012-12-17T11:56:40.187 回答
0

只需考虑这个简单的假设代码,让我们假设......符合您的描述:

Exp ex = new NewExp(); 
try {
ex.generate(); //It should throw an exception, but has no such method signature. 
} catch(AnException e) { //Nope, not allowed.
 ...
}
于 2012-12-17T11:46:32.580 回答
0

是否需要抛出已检查的异常。你能把它包装在运行时异常中吗?

public void generate() {
     try {
     ....
     } catch (IOException e ){
        RuntimeException re = new RuntimeException();
        re.initCause(e);
        throw re;
     }   
}

(没有检查这个进行编译,但它应该给你一个大致的想法

于 2012-12-17T11:49:50.640 回答
0

如果您正在重写一个方法,则超类中的重写方法只能声明抛出该异常(已检查)或其超类。否则你会失去多态性,因此在 Java 中是不允许的

于 2012-12-17T11:51:59.573 回答
0
  1. 我们不能在被覆盖的方法中引入新的检查异常,但可以有子检查异常或与父类中处理的相同异常。即使我们这样做了,如果我们使用父引用来引用子对象,那么编译器将强制捕获父类方法中声明的异常,然后看下面的示例:

    class Parent{
                public void method throws IOException{
                }
        } 
    
        class Child extends Parent{
               public void method throws SQLException{
               }      
        }
    
        class Test{
        public static void main(){
              Parent p=new Child();
    
             try{
              p.method();
             }catch(IOException e){
                e.printStackTrace();
             }
        }
    }
    

    在上面的程序中,子类方法抛出 SQLException 但 Compiler 会强制捕获 IOException。因为在编译时编译器不知道子对象是从父引用中引用的。但是我们可以声明任何未经检查的异常,因为编译器不会强制执行 try/ctach 或为它们抛出异常。

于 2017-05-16T18:04:38.167 回答