我有一种方法,应该在找到对象后返回它。
如果找不到,我应该:
- 返回null
- 抛出异常
- 其他
我有一种方法,应该在找到对象后返回它。
如果找不到,我应该:
Answers:
如果您一直期望找到一个值,那么如果缺少该值,则抛出异常。异常将意味着存在问题。
如果该值可能缺失或存在,并且对于应用程序逻辑均有效,则返回null。
更重要的是:您在代码的其他位置做什么?一致性很重要。
GetPersonById(25)
如果该人已被删除将抛出该异常,但GetPeopleByHairColor("red")
将返回空结果。因此,我认为参数说明了期望值。
仅当确实是错误时才抛出异常。如果该对象的预期行为不存在,则返回null。
否则,这是一个优先事项。
通常,如果方法应始终返回对象,则应使用异常。如果您预计偶尔会出现null并希望以某种方式进行处理,请使用null。
无论您做什么,我都强烈建议您不要使用第三个选项:返回一个字符串“ WTF”。
如果null从不表示错误,则只需返回null。
如果null始终是错误,则抛出异常。
如果null有时是一个例外,则编写两个例程。一个例程引发异常,另一个例程是布尔测试例程,该布尔测试例程在输出参数中返回对象,如果未找到对象,则例程返回false。
很难滥用Try例程。忘记检查null确实很容易。
所以当null是一个错误时,您只需编写
object o = FindObject();
当null不是错误时,您可以编写类似
if (TryFindObject(out object o)
// Do something with o
else
// o was not found
find
和findOrFail
从Laravel雄辩
TryFindObject
方法返回的多属性对象吗?对于不想花时间定义封装多个值的对象的程序员来说,元组似乎更是一种懒惰的范例。基本上,所有元组都是核心。
我只是想概括一下前面提到的选项,并在其中添加一些新选项:
或者您可以结合使用以下选项:
提供您的getter的多个重载版本,以便调用者可以决定要走的路。在大多数情况下,只有第一个具有搜索算法的实现,而其他仅包含第一个:
Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);
即使您选择仅提供一种实现,也可能希望使用类似的命名约定来阐明您的合同,并且如果您决定还添加其他实现,则它可以帮助您。
您不应过度使用它,但它可能会有所帮助,尤其是在编写一个将在具有许多不同错误处理约定的数百个不同应用程序中使用的助手类时。
Expected<T> findObject(String)
其中Expected<T>
具有的功能orNull()
,orThrow()
,orSupplied(Supplier<T> supplier)
,orDefault(T default)
。这从错误处理中提取了数据的获取
使用空对象模式或引发异常。
Person somePerson = personRepository.find("does-not-exist");
假设此方法为ID返回空对象does-not-exist
。那么正确的行为是somePerson.getAge()
什么呢?目前,我还不确定空对象模式是实体查找的正确解决方案。
引发异常的优点:
有关示例的更多说明,请参见:http : //metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/
取决于找不到对象的含义。
如果状态正常,则返回null。这只是偶尔会发生的事情,呼叫者应进行检查。
如果是错误,则引发异常,调用者应决定如何处理丢失对象的错误情况。
最终,两者都会起作用,尽管大多数人普遍认为,只有在发生异常的情况下才使用Exceptions是一个好习惯。
这里还有更多建议。
如果返回一个集合,请避免返回null,而返回一个空集合,这会使枚举更容易处理,而无需先执行null检查。
多个.NET API使用thrownOnError参数的模式,该模式使调用者可以选择是否找到对象是否真的是例外情况。Type.GetType就是一个例子。BCL的另一个常见模式是TryGet模式,其中返回一个布尔值,并且该值通过输出参数传递。
在某些情况下,您还可以考虑使用Null Object模式,该模式可以是默认行为,也可以是没有行为的版本。关键是避免在整个代码库中进行空检查。有关更多信息,请参见此处http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx
返回null而不引发异常,并在API文档中清楚地记录了可能返回null的可能性。如果调用代码不遵循API并检查null大小写,则很可能会导致某种“空指针异常” :)
在C ++中,我可以想到3种不同的方式来设置找到对象的方法。
选项A
Object *findObject(Key &key);
找不到对象时返回null。漂亮又简单。我会去的。以下替代方法适用于不讨厌实物的人。
选项B
void findObject(Key &key, Object &found);
传递对将接收对象的变量的引用。当找不到对象时,该方法引发异常。如果不是真正希望找不到对象,则此约定可能更合适-因此,您抛出异常以表示这是意外情况。
选项C
bool findObject(Key &key, Object &found);
当找不到对象时,该方法返回false。与选项A相比,此选项的优势在于您可以通过一个清晰的步骤检查错误情况:
if (!findObject(myKey, myObj)) { ...
不幸的是,JDK是不一致的,如果您尝试访问资源束中不存在的键,则不会发现异常,并且当您从map请求值时,如果不存在该值,则会得到null。因此,如果发现的值可以为null,那么我将更改赢家的答案,如果找不到,则引发异常,否则返回null。因此,请遵循带有一个例外的规则,如果您需要知道为什么找不到值,请始终提出例外,或者。
如果该方法返回一个集合,则返回一个空集合(如上述)。但请不要使用Collections.EMPTY_LIST之类的!(对于Java)
如果该方法检索单个对象,则您有一些选择。
如果您决定返回null,请当心。如果您不是项目中唯一的程序员,则在运行时将获得NullPointerExceptions(使用Java或其他语言)。因此,请勿返回在编译时未检查的null。
null
。查看更多投票答案。
如果您使用的是引发异常的库或其他类,则应将其重新抛出。这是一个例子。Example2.java就像库,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();
}
}
}
范例.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\"");
}
}