Java 用于决定已检查和未检查异常的清晰而简单的规则

Java 用于决定已检查和未检查异常的清晰而简单的规则,java,exception-handling,Java,Exception Handling,既然这个问题有很多不明确之处,我们能想出一些清晰、简单和易于使用的规则吗 这是第一次尝试,这三条规则应该对所有情况都足够了 第一条规则基于一个共同原则,即方法的实现细节不应向调用方公开: 规则1: 选中的异常不应向调用方公开实现详细信息: 您可以这样测试它:如果您完全更改了实现,但仍然期望该方法履行其契约(如在重构中),抛出异常是否仍然有意义? 如果是,那么它应该是一个选中的异常,因为它不是实现细节,而是方法填充的用例的一部分。 如果否,则应取消选中异常,因为它是不应向调用方公开的实现细节 如

既然这个问题有很多不明确之处,我们能想出一些清晰、简单和易于使用的规则吗

这是第一次尝试,这三条规则应该对所有情况都足够了


第一条规则基于一个共同原则,即方法的实现细节不应向调用方公开:

规则1: 选中的异常不应向调用方公开实现详细信息: 您可以这样测试它:如果您完全更改了实现,但仍然期望该方法履行其契约(如在重构中),抛出异常是否仍然有意义? 如果是,那么它应该是一个选中的异常,因为它不是实现细节,而是方法填充的用例的一部分。 如果否,则应取消选中异常,因为它是不应向调用方公开的实现细节

如果根据规则1,应检查例外情况,然后应用规则2:

规则2:由于检查异常是方法契约的一部分,因此违反方法契约不能成为检查异常。 例如,此方法从其参数执行sql查询:

executeSqlQuery(字符串sqlQuery)

若调用者提供的字符串不是sql查询,那个么他违反了方法的输入条件,并且必须取消选中产生的异常

如果根据第2条规则,例外情况似乎仍处于选中状态,则应用第3条规则,检查该方法是否遵循另一种最佳实践:单一责任原则

规则3:方法应该只做一件事。 例如方法

List.get(int索引)

正确地做的只有一件事:从列表中返回所需的元素。并且不尝试实现另一个常见用例:检查元素是否存在。 另一方面,方法

findById(长id)抛出RecordNotFoundException

试图混合这两个函数是不正确的,这会迫使所有调用方总是在记录未找到时使用用例,即使他们知道记录存在。


是否缺少一些规则,或者我们是否可以进一步简化和澄清规则


背景: 在这个问题上有许多不同的观点。有很多“激进”解决方案的支持者,比如从不使用检查异常(一些java书籍或C#的设计者),或者几乎所有东西都应该是检查异常(java.io包中的IOException或JDBC中的SQLException)。
至少有相同数量的视图建议使用这两种类型,但它们提供了主观和模糊的规则来决定它们之间的关系,而这些规则没有冗长的解释,而这些解释往往是缺失的,而不是带来更多的混乱(例如:如果呼叫者从异常中恢复是合理的,那么它应该被检查。再次尝试呼叫是否是合理的恢复?对于某些客户来说可能是。合理和恢复的词太模糊了。)

嗯,这个问题在官方中得到了回答,事实上:

下面是一条底线指导原则:如果可以合理地期望客户机从异常中恢复,则将其设置为已检查异常。如果客户机无法执行任何操作来从异常中恢复,则将其设置为未检查异常

在我看来,这是一条非常明确、简单的规则

编辑:你的背景编辑很好地解释了你的困惑和沮丧。如果你想,我可以想出一个更简单的规则:

始终可用。尽可能做到实用。努力保持一致

关键是异常处理是可能抛出的方法的用户必须做的事情。遗憾的是,Java迫使编写该方法的人为该方法的用户做出选择。因此,我稍微倾向于“从不检查”另一方面,因为您的方法总是可用的。对于某些情况,例如网络I/O,强制用户构建一些错误处理可能是非常实际的,但事实并非如此。如果您问自己,嗯,我最近的400个方法都抛出了
RuntimeError
s,现在是否应该抛出一个选中的异常ng一致性可能会使使用库更加实用


可悲的是,这条规则更简单,但并不清晰,因为至少实用和一致性是非常主观的概念。所以,你现在要面对的是一个真正的风格问题。

嗯,这个问题在官方中得到了回答,事实上:

下面是一条底线指导原则:如果可以合理地期望客户机从异常中恢复,则将其设置为已检查异常。如果客户机无法执行任何操作来从异常中恢复,则将其设置为未检查异常

在我看来,这是一条非常明确、简单的规则

编辑:你的背景编辑很好地解释了你的困惑和沮丧。如果你想,我可以想出一个更简单的规则:

始终可用。尽可能做到实用。努力保持一致

关键是异常处理是可能抛出的方法的用户必须做的事情。遗憾的是,Java迫使编写该方法的人为该方法的用户做出选择。因此,我稍微倾向于“从不检查”另一方面,因为您的方法总是可用的。对于某些情况,例如网络I/O,强制用户构建一些错误处理可能是非常实际的,但事实并非如此。如果您问自己,嗯,我最近的400个方法都抛出了
RuntimeError
s,现在是否应该抛出一个选中的异常ng一致性可能会使使用库更加实用

可悲的是,这条规则更简单,但并不清晰,因为至少实用和一致的概念是非常主观的