代码之家  ›  专栏  ›  技术社区  ›  vitaut

在接口方法的throws子句中放入什么?

  •  5
  • vitaut  · 技术社区  · 15 年前

    假设我有接口 I 两个班 A B 实现它。 方法的实现 f 这个接口的 一个 抛出一组异常并将实现 再投一盘。这些异常的唯一共同祖先是 java.lang.Exception . 申报合理吗 f型 投掷 java.lang.Exception异常 在这种情况下?还有别的选择吗?

    我问的原因一方面是 java.lang.Exception异常 在我看来过于笼统,另一方面,考虑到其他可能的实现,列出所有异常似乎不切实际。

    例子:

    interface I {
        void f() throws Exception;
    }
    
    class A implements I {
        public void f() throws IOException {}
    }
    
    class B implements I {
        public void f() throws InterruptedException {}
    }
    
    3 回复  |  直到 15 年前
        1
  •  16
  •   Adrian Pronk    15 年前

    使用接口的原因是抽象出实现细节。

    通过抛出这些异常,您将暴露可能应该被抽象掉的实现细节。

    也许最好定义一个新的异常。然后f()的每个实现都会捕获它所知道的异常,并抛出新的异常,这样您就可以:

    interface I {
        void f() throws MyException;
    }
    
    class A implements I {
        public void f() throws MyException {
             try {
                 ...
             } catch (IOException e) {
                 throw new MyException(e);
             }
        }
    }
    
    class B implements I {
        public void f() throws MyException {
             try {
                 ...
             } catch (InterruptedException e) {
                 throw new MyException(e);
             }
        }
    }
    

    通过包装实现异常,您仍然将其暴露给调用方,并且在调用远程方法时,这可能会使您感到不适。在这些情况下,您需要做更多的工作以通用的方式返回有用的信息。

    编辑
    关于正确的方法似乎有点争论。

    当我们调用f()时,我们需要如下代码:

    I instanceOfI = getI();
    try {
        instanceOfI.f();
    }
    catch ( /* What should go here ? */ )
    

    归根结底,是什么样的异常类可以放在catch块中。
    用OP的原始代码我们可以抓到 Exception 然后再看看我们有哪些子类,或者不取决于需求。或者我们可以单独捕获每个子类,但是当新实现抛出不同的异常时,我们必须添加catch块。

    如果我们使用运行时异常,结果会大同小异,只是我们可以选择将异常处理推迟到调用方方法,甚至不考虑异常的可能性。

    如果我们使用我的建议使用一个新的、包装好的异常,那么这意味着我们必须捕获 MyException 然后尝试查看可用的其他信息。这基本上变得非常像使用异常,但是需要额外的工作来获得 bespoke 可根据用途定制的例外情况。

        2
  •  3
  •   Armand    15 年前

    这似乎有点落后。您应该抛出与您的接口相关且可能特定的异常,或者根本不抛出。更改实现以包装公共异常类(尽管不是 Exception 本身)。如果无法处理此问题,则可能需要将实现中的异常包装为运行时异常。

        3
  •  1
  •   Peter Lawrey    15 年前

    你可以声明你抛出的异常

    void f() throws IOException, InterruptedException;
    

    如果你使用一个像样的IDE,它会帮你纠正这个错误。我只是在方法中抛出异常,IDE给了方法子句及其接口添加选项。