针对异常的Java接口的正确设计

 mobiledu2502881767 发布于 2023-02-13 16:58

我试图了解如何在Java中正确定义接口,以及如何在语言(和运行时)中处理异常.

注意:也许这个问题已经被提出并得到了充分的回答,但是我对SO(和其他网站)的搜索没有发现任何直接解决设计问题和我所提出的权衡的问题.我很乐意删除这个问题,如果可以找到一个能回答我问题的类似问题.我为这个冗长的问题提前道歉,但我想尽可能清楚地说明问题.我也知道关于检查异常的争议,但由于我无法改变语言并且仍然必须在其中工作,我想选择能够导致最少痛苦的方法.长期.

我遇到的反复出现的问题是,当我尝试定义自己的接口时,我面临着如何指定允许接口成员使用哪些(如果有)异常的选择.麻烦的是我无法知道哪些异常是有意义的,因为我不知道我的界面的所有可能实现可能是什么.为了举个例子,假设我们有以下接口:

// purely hypothetical interface meant to illustrate the example...
public interface SegmentPartition {
    // option 1
    bool hasSegment(Segment s);
    // option 2
    void addSegment(Segment s) throws Exception;
    // option 3
    bool tryAddSegment(Segment s) throws TimeoutException, IOException, ParseException, XmlException, SQLException;
    // option 4
    void optimizeSegments() throws SegmentPartitionException;
}

此接口应该预先声明哪些异常类型?我看到的选项是:

    不申报任何异常,实现只能扔RuntimeException

    将每个方法声明为throw Exception

    尝试预测对此接口有意义的每个可能的异常类型,并将它们声明为throwable异常.

    创建我自己的异常类型(例如SegmentException)并要求根据需要抛出内部异常以获得更多细节.

每种方法都存在问题,而且并不完全清楚所有的权衡可能是什么,我已经提到了每种情况的一些权衡.理想情况下,我不希望实现抛出任何异常,但这并不总是一个实际的限制.

对于选项1,问题是许多可能抛出的异常类型不是从RuntimeException派生的(例如IOException或TimeoutException).当然,我可以将这些特定的异常添加到接口,然后允许抛出其他RuntimeExceptions,但那么用户定义的异常呢?这似乎是一个糟糕的选择.

使用选项2,我们最终得到一个界面,看起来它可能导致任何异常(我认为是真的),并且没有提供实际应该抛出的实现者的指导.界面不再是自我记录.更糟糕的是,此接口的每个调用站点必须被声明为抛出异常或将每个调用包装到此接口的方法中try{} catch(Exception),或者创建一个捕获异常的块并尝试判断它是否被接口实现或其他东西抛出在那个街区.呸.或者,使用此接口的代码可以捕获实现可能抛出的特定异常,但是它违反了以接口开头的目的(因为它需要调用者知道实现的运行时类型).在实践中,这是与我所知道的大多数其他语言最接近异常(C++,C#,Scala等)的选项.

使用选项3,我必须特别预测可以为我的接口定义的潜在实现,并声明最适合它们的异常.因此,如果我预计我的接口可能通过远程,不可靠的连接实现,我会添加TimeoutException,如果我预计它可能使用外部存储实现,我将包括IOException,依此类推.我几乎可以肯定会弄错...这意味着我将继续搅拌界面,因为新的实现范式浮出水面(当然,它会破坏所有现有的实现并要求它们将非敏感的异常声明为抛出).这种方法的另一个问题是导致丑陋,重复的代码......特别是对于具有许多方法的大型接口(是的,有时需要这些),然后需要在每个实现点重复这些方法.

使用选项4,我必须创建自己的异常类型,以及随之而来的所有行李(可序列化,嵌套和内部异常,提出合理的层次结构等).这里不可避免地发生的事情是,每种接口类型都有一种异常类型:InterfaceFoo + InterfaceFooException.除了需要的代码膨胀之外,真正的问题是异常类型并不意味着什么......它只是一种用于将特定接口的所有错误条件捆绑在一起的类型.在某些情况下,也许您可​​以创建一些异常类型的子类来指示特定的失败模式,但即使这样也是有问题的.

那么一般来说,在这里做什么是正确的?我意识到可能没有一个削减和干燥的规则,但我很好奇Java开发人员选择做什么.

谢谢你.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有