2012-08-06 73 views
3

假设在Java中,我使用一个预先存在的接口是相当普遍的新checked异常重写Java接口

public interface Generator { 
    public String generate(); 
} 

,我有我自己的类

public class FromFileGenerator implements Generator { 
    ... 
    public String generate() throws FileNotFoundException { 
     String output = //read from some file 
     return file; 
    } 
} 

Java编译器骂我是因为generate()的实现包含一个未在原始签名(FileNotFoundException)中指定的异常。但是,显然这个异常不属于界面,但在实现类中也是不容忽视的。如何在不简单失败的情况下解决这个问题?

+3

接口定义合同。检查异常是方法签名的一部分,因此也是方法合同。您必须满足*确切的合同*才能实现界面。 – 2012-08-06 20:44:29

+3

@pst - 不完全。实现方法不会被声明为抛出它覆盖的方法的所有检查过的异常;它只是不能添加任何新的检查异常。 – 2012-08-06 20:48:22

+0

@TedHopp啊。记忆库更正。谢谢:)我想这是有道理的。 – 2012-08-06 21:26:30

回答

2

你可以用实施例外在unchecked异常并抛出:

public class FromFileGenerator implements Generator { 
    ... 
    public String generate() { 
     try { 
      String output = //read from some file 
      return file; 
     } catch (IOException ioe) { 
      throw new RuntimeException(ioe); 
     } 
    } 
} 
+0

对我来说足够了。 – donnyton 2012-08-08 19:22:42

13

您不能将检查的异常添加到隐藏,覆盖或实现其他方法的方法的声明中。您需要在该方法中捕获异常并对其执行其他操作(例如返回null,或者抛出未经检查的异常,可能包装检查的异常)。

Java Language Specification, §8.4.8.3

,它覆盖或隐藏的另一种方法,包括实现接口中定义的抽象方法,可以不声明为抛出多个检查的异常比重写或隐藏的方法的方法的方法。

4

不幸的是,没有办法很好地解决这个问题:异常规格接口的一部分,所以如果有人谁的方案,以你的Generator接口不希望看到FileNotFoundException,它不应该来他们的时候他们使用FromFileGenerator

一种常见的方式来解决它是通过引入一个共同的例外,并且它包裹FileNotFoundException

public class GeneratorException extends Exception { 
    public GeneratorException(Exception inner) { 
     super(inner); 
    } 
} 
public interface Generator { 
    public String generate() throws GeneratorException; 
} 
public class FromFileGenerator implements Generator { 
... 
    public String generate() throws GeneratorException { 
     try { 
      String output = //read from some file 
      return file; 
     } catch (FileNotFoundException fnf) { 
      throw new GeneratorException(fnf); 
     } 
    } 
} 
+0

由于相同的原因,这不会编译:接口没有指定任何异常,所以实现不能抛出检查的异常。 – Tom 2012-08-06 20:55:36

+0

@Tom你是对的,我创建了一个常见的异常类,但忘了添加一个'throw'声明!谢谢,这现在已经修复了。 – dasblinkenlight 2012-08-06 20:57:40

4

接口是合同

enter image description here

所以,你需要定义前期。

因此,您可以尝试,抓住您的方法体或修改合同。

3

对此的常见解决方案是将异常封装在未经检查的异常中。所以你的班级可能看起来像这样:

public class FromFileGenerator implements Generator { 
    ... 
    public String generate() throws FileNotFoundException { 
     try { 
      String output = //read from some file 
      return output 
     } catch (FileNotFoundException e) { 
      throw new IllegalStateException(e); 
     } 
    } 
} 

更好的办法是改变接口有自己的检查异常。然后,您可以将FileNotFoundException从转换为上面未经检查的IllegalStateException的相同方式转换为检查的异常。