我使用java语言,我有一个方法,如果它被找到,应该返回一个对象。
如果没有找到,我是否应该:
返回null 抛出异常 其他
哪一个是最好的实践或习语?
我使用java语言,我有一个方法,如果它被找到,应该返回一个对象。
如果没有找到,我是否应该:
返回null 抛出异常 其他
哪一个是最好的实践或习语?
当前回答
我只是想概括一下之前提到的选项,并添加一些新的选项:
返回null 抛出异常 使用空对象模式 为您的方法提供一个布尔参数,以便调用者可以选择是否希望您抛出异常 提供一个额外的参数,以便调用者可以设置一个值,如果没有找到值,则返回该值
或者你可以把这些选项结合起来:
提供getter的多个重载版本,以便调用者可以决定采用哪种方式。在大多数情况下,只有第一个有搜索算法的实现,其他的只是围绕着第一个:
Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);
即使您选择只提供一个实现,您也可能希望使用这样的命名约定来阐明您的契约,并且它有助于您决定添加其他实现。
你不应该过度使用它,但它可能是有帮助的,特别是当你编写一个helper类时,你将在数百个不同的应用程序中使用许多不同的错误处理约定。
其他回答
如果您总是希望找到一个值,那么如果缺少该值则抛出异常。这个例外意味着有问题。
如果该值可以缺失或存在,并且两者都对应用程序逻辑有效,则返回null。
更重要的是:在代码的其他地方做什么?一致性很重要。
这里还有一些建议。
如果返回一个集合,避免返回null,返回一个空集合,这使得枚举更容易处理,而不需要先进行空检查。
一些. net API使用thrownOnError参数的模式,如果对象没有找到,调用者可以选择是否真的是异常情况。类型。GetType就是一个例子。BCL的另一个常见模式是TryGet模式,其中返回一个布尔值,并通过输出参数传递值。
在某些情况下,您还可以考虑Null Object模式,它可以是默认的,也可以是没有行为的版本。关键是避免在整个代码库中进行空检查。更多信息请参见这里链接
如果对于客户端代码来说,知道已找到和未找到之间的区别很重要,并且这应该是一个例程行为,那么最好返回null。然后客户端代码可以决定要做什么。
在数据层代码中,我有时使用以下代码,允许调用者决定“对象未找到”是否意味着发生了错误。
DataType GetObject(DBConnection conn, string id, bool throwOnNotFound) {
DataType retval = ... // find object in database
if (retval != null || ! throwOnNotFound) {
return retval;
} else {
throw new NoRowsFoundException("DataType object with id {id} not found in database");
}
}
DataType GetObject(DBConnection conn, string id) {
return GetObject(conn, id, true);
}
如果您正在使用抛出异常的库或其他类,则应该重新抛出异常。这里有一个例子。Example2.java类似于library,而Example.java使用它的对象。Main.java就是一个处理这个异常的例子。您应该向调用端的用户显示有意义的消息和堆栈跟踪(如果需要)。
Main.java
public class Main {
public static void main(String[] args) {
Example example = new Example();
try {
Example2 obj = example.doExample();
if(obj == null){
System.out.println("Hey object is null!");
}
} catch (Exception e) {
System.out.println("Congratulations, you caught the exception!");
System.out.println("Here is stack trace:");
e.printStackTrace();
}
}
}
Example.java
/**
* Example.java
* @author Seval
* @date 10/22/2014
*/
public class Example {
/**
* Returns Example2 object
* If there is no Example2 object, throws exception
*
* @return obj Example2
* @throws Exception
*/
public Example2 doExample() throws Exception {
try {
// Get the object
Example2 obj = new Example2();
return obj;
} catch (Exception e) {
// Log the exception and rethrow
// Log.logException(e);
throw e;
}
}
}
Example2.java
/**
* Example2.java
* @author Seval
*
*/
public class Example2 {
/**
* Constructor of Example2
* @throws Exception
*/
public Example2() throws Exception{
throw new Exception("Please set the \"obj\"");
}
}