java api设计 – NULL或Exception

返回null值或从API方法抛出exception是否更好?

返回null需要全部进行丑陋的空检查,如果未选中返回则会导致严重的质量问题。

抛出exception会强制用户对错误条件进行编码,但由于Javaexception冒泡并迫使调用者代码处理它们,因此通常使用自定义exception可能是一个坏主意(特别是在java中)。

有什么健全和实用的建议?

我认为答案完全取决于您的应用程序的上下文,以及您认为是“特殊情况”与程序员错误。

例如,如果编写XML解析器,您可以选择实现以下方法:

/** * Returns first child element with matching element name or else * throws an exception. Will never return null. */ Element getMandatoryChildElement(Element parent, String elementName) throws MissingElementException; 

…因为这种方法允许您在单个逻辑块中实现消息解析代码,而无需在检索每个元素或属性后检查消息是否格式正确。

如果null是可接受的返回值(即,它可以由有效输入而不是错误情况产生),则返回null ; 否则抛出exception。

我完全不理解你的陈述,即检查exception可能是一个坏主意,因为调用者被迫处理它们 – 这是检查exception的全部要点。 它可以防止在没有正确处理的情况下传播到代码中的错误情况。

Josh Bloch建议返回空对象或“单元”对象来代替空值。 查看Effective Java以获取大量有用的Java花絮。

我的观点是

当返回类型是集合或数组时,永远不会返回NULL。 如果没有返回值,则返回空集合或空数组。

这消除了对空检查的需要。

好的做法:

 public List getStudentList() { int count = getStudetCount(); List studentList = new ArrayList(count); //Populate studentList logic return studentList; } 

糟糕的做法: 。 永远不要写下面的代码。

 public List getStudentList() { int count = getStudetCount(); if(count == 0) { return null; } //Populate studentList logic return studentList; } 

在Practial API Design中 ,作者建议不要返回null值( 参见第24页 )。

他的主要观点是,它导致了对null值和更多文档的检查的激增。

我还强烈建议阅读该领域的权威人士(T. Hoare)的“ 空参考:十亿美元的错误 ”。

我倾向于将null返回到“getXXX”方法,例如,从数据库中获取一些东西:User getUserByName(String name)可以让我返回null

但是,如果您需要通过调用方法获取所需内容,则抛出exception:ex:getDatabaseConnection()必须始终返回连接,并且永远不会返回null

并且,对于返回集合或数组的方法,NEVER返回null。 返回一个空的集合/数组

这实际上取决于您希望如何处理这种情况。 如果它确实是一个错误条件,那么抛出exception。 如果null是可接受的输出,则仅记录它并让用户处理它。

A同意其他人,如果null是可接受的返回值,则返回它,否则不返回。

我想补充的是,您还可以区分已检查和未检查的exception。 在某些情况下,建议使用未经检查的exception,例如,API的用户可能无法处理该exception。 Spring Framework经常使用未经检查的exception,这使得代码通常更容易阅读,但有时难以追踪错误。

如果您有内部库错误(意外),请让运行时exception传播。 如果库代码中存在错误,则客户端将崩溃。 修复库中的错误。 不要捕获所有并返回特定于库的exception,这不会有任何好处。

如果您希望(有时)出现问题,请将其构建到API中。 这是基于您不应该对正常程序流使用exception的原则。

例如:

 ProcessResult performLibraryTask(TaskSpecification ts) 

这样你就可以让ProcessResult指出错误条件:

 ProcessResult result = performLibraryTask(new FindSmurfsTaskSpecification(SmurfColor.BLUE)); if (result.failed()) { throw new RuntimeException(result.error()); } 

此方法类似于return null方法,但您可以将更多信息发送回客户端。

编辑:

对于不符合约定协议的交互,您可以抛出可以记录的运行时错误。 例如:

 if (currentPeriod().equals(SmurfColor.BLUE) && SmurfColor.GREEN.equals(taskSpecification.getSmurfColor()) { throw new IllegalStateException("Cannot search for green smurfs during blue period, invalid request"); } 

请注意,这是由于违反合同的互动,预计不会发生。

我通常会在JDK中看一个类似的例子。

在访问器的情况下,使用Null是有意义的。

Null应该用于指示丢失或未知的数据。

对于其他一切,它通常代表处理中的错误。

现在,我们有两个选项,运行时与编译时。 以下是我如何寻找类比的例子。

让我们从ArrayIndexOutOfBoundException中提取一个例子。 访问或改变元素是一种非常常见的操作。

如果检查过,则消费代码将非常混乱。 此外,通常开发人员倾向于意识到可能导致ArrayIndexOutOfBounException的情况,并且可以通过编写好的代码来避免它。

另一方面,如果我们有一段代码打开一个文件,这可能是由于外部依赖(缺少文件或没有足够的权限)引起的,并且没有根植于程序中的错误,最好检查exception。