我使用java语言,我有一个方法,如果它被找到,应该返回一个对象。
如果没有找到,我是否应该:
返回null 抛出异常 其他
哪一个是最好的实践或习语?
我使用java语言,我有一个方法,如果它被找到,应该返回一个对象。
如果没有找到,我是否应该:
返回null 抛出异常 其他
哪一个是最好的实践或习语?
当前回答
首选返回null——
如果调用者在不检查的情况下使用它,异常就会在那里发生。
如果调用者并没有真正使用它,不要给他一个try/catch块
其他回答
只有在确实是错误时才抛出异常。如果对象不存在是预期行为,则返回null。
否则就是个人喜好的问题了。
返回空值而不是抛出异常,并在API文档中清楚地记录空返回值的可能性。如果调用代码不遵守API并检查空情况,它很可能会导致某种“空指针异常”:)
在c++中,我可以想到3种不同的方法来设置查找对象的方法。
选择一个
Object *findObject(Key &key);
当找不到对象时返回null。很好很简单。我选这个。下面的替代方法是为那些不讨厌out-params的人准备的。
选项B
void findObject(Key &key, Object &found);
传入一个将接收该对象的变量引用。当找不到对象时,该方法抛出异常。如果不是真的期望找不到对象,那么这种约定可能更适合——因此您可以抛出异常来表示这是一个意外情况。
C选项
bool findObject(Key &key, Object &found);
当找不到对象时,该方法返回false。与选项A相比,这个选项的优点是,您可以在一个明确的步骤中检查错误情况:
if (!findObject(myKey, myObj)) { ...
如果您正在使用抛出异常的库或其他类,则应该重新抛出异常。这里有一个例子。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\"");
}
}
这取决于你的方法。如果你的方法应该总是返回一个有效的对象,但却没有找到,那么抛出异常就是正确的方法。如果该方法只是返回一个可能存在也可能不存在的对象(比如联系人的图像),则不应该引发错误。
你可能还想公开一个返回布尔值true/false的方法,如果这个方法实际上会返回一个对象,这样你就不必a)检查null或b)捕捉异常
我只是想概括一下之前提到的选项,并添加一些新的选项:
返回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类时,你将在数百个不同的应用程序中使用许多不同的错误处理约定。