检索方法应该返回#39;null#39;还是无法产生返回值时引发异常? [关闭]
想改善这个问题吗? 更新问题,以便通过编辑此帖子以事实和引用的形式回答。
3年前关闭。
我有一种方法,应该在找到对象后返回它。
如果找不到,我应该:
- 返回null
- 抛出异常
- 其他
#1楼
如果该方法返回一个集合,则返回一个空集合(如上述)。 但请不要使用Collections.EMPTY_LIST之类的! (对于Java)
如果该方法检索单个对象,则您有一些选择。
- 如果该方法应始终找到结果,并且是找不到对象的真正异常情况,则应引发异常(在Java中:请未经检查的Exception)
- (仅Java)如果可以忍受该方法引发检查异常,则引发项目特定的ObjectNotFoundException或类似事件。 在这种情况下,如果您忘记处理异常,编译器会告诉您。 (这是我对Java中找不到的东西的首选处理。)
- 如果您说没关系,如果找不到对象,并且您的方法名称类似于findBookForAuthorOrReturnNull(..),则可以返回null。 在这种情况下, 强烈建议您使用某种静态检查或编译器检查,以防止在没有空检查的情况下取消对结果的引用。 如果是Java,可以是例如。 FindBugs(请参阅http://findbugs.sourceforge.net/manual/annotations.html上的 DefaultAnnotation)或IntelliJ-Checking。
如果您决定返回null,请当心。 如果您不是项目中唯一的程序员,则在运行时将获得NullPointerExceptions(使用Java或其他语言)。 因此,请勿返回在编译时未检查的null。
#2楼
我更喜欢只返回一个null,然后依靠调用方对其进行适当处理。 (由于缺少更好的词)例外是,如果我绝对“确定”此方法将返回一个对象。 在那种情况下,失败是异常的,应该抛出。
#3楼
与您使用的API保持一致。
#4楼
使用空对象模式或引发异常。
#5楼
如果了解客户端代码之间的区别很重要,并且这应该是常规行为,那么最好返回null。 客户代码然后可以决定要做什么。
#6楼
通常,它应该返回null。 调用该方法的代码应决定是引发异常还是尝试其他事情。
#7楼
这实际上取决于您是否希望找到对象。 如果您遵循这样的学派,那就应该使用异常来表示某些东西,好吧,错了,异常发生了,那么:
- 找到对象; 返回对象
- 找不到对象; 抛出异常
否则,返回null。
#8楼
仅当确实是错误时才引发异常。 如果该对象的预期行为不存在,则返回null。
否则,这是一个优先事项。
#9楼
如果您一直期望找到一个值,那么如果缺少该值,则抛出异常。 例外意味着存在问题。
如果该值可能缺失或存在,并且对于应用程序逻辑均有效,则返回null。
更重要的是:您在代码的其他位置做什么? 一致性很重要。
#10楼
通常,如果方法应始终返回对象,则应使用异常。 如果您预计偶尔会出现null并希望以某种方式进行处理,请使用null。
无论您做什么,我都强烈建议不要使用第三个选项:返回一个表示“ WTF”的字符串。
#11楼
取决于找不到对象的含义。
如果状态正常,则返回null。 这只是偶尔会发生的事情,呼叫者应进行检查。
如果是错误,则引发异常,调用者应决定如何处理丢失对象的错误情况。
最终,两者都会起作用,尽管大多数人通常认为,仅在发生异常的情况下才使用Exceptions是一种很好的做法。
#12楼
只要应该返回对对象的引用 ,则返回NULL应该很好。
但是,如果返回的是满是血腥的东西(例如在C ++中,如果您这样做:“ return blah;”而不是“ return&blah;”(或“ blah”是一个指针)),那么您将无法返回NULL,因为它是在这种情况下,抛出异常或返回没有设置成功标志的空白对象就是我要解决的问题。
#13楼
返回null而不是引发异常,并在API文档中清楚地记录了返回空值的可能性。 如果调用代码不支持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)) { ...
#14楼
不要以为任何人都提到了异常处理的开销-需要额外的资源来加载和处理异常,因此,除非它是真正的应用程序终止或进程停止事件(前进会造成弊大于利),否则我会选择返回一个调用环境可以认为合适的值。
#15楼
我同意这里似乎达成的共识(如果“未找到”是正常的可能结果,则返回null;如果情况的语义要求始终找到该对象,则抛出异常)。
但是,根据您的特定情况,存在第三种可能有意义的可能性。 您的方法可以在“未找到”条件下返回某种默认对象,从而确保调用代码可以始终收到有效对象,而无需进行空检查或异常捕获。
#16楼
如果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
#17楼
或退回期权
一个选项基本上是一个容器类,它迫使客户处理展位情况。 Scala有这个概念,请查询它的API。
然后,在该对象上具有T getOrElse(T valueIfNull)之类的方法,它们要么返回找到的对象,要么由客户指定。
#18楼
返回一个null,异常恰好是:您的代码执行了某些意外的操作。
#19楼
这取决于您的语言和代码是否能促进:LBYL(飞跃之前先看一下)或EAFP(更容易要求宽恕而不是允许)
LBYL说您应该检查值(因此返回null)
EAFP表示只需尝试操作,看看它是否失败(引发异常)
尽管我在上面也同意。.异常/错误条件应使用异常,使用检查时最好返回null。
EAFP与LBYL在Python中的比较:
http://mail.python.org/pipermail/python-list/2003-May/205182.html(Web 存档 )
#20楼
在某些函数中,我添加了一个参数:
..., bool verify = true)
True表示抛出,false表示返回一些错误返回值。 这样,无论使用此功能的人都有两个选择。 默认值应为true,以使那些忘记错误处理的人受益。
#21楼
只是问问自己:“找不到对象是一种特殊情况吗?” 如果预期在程序的正常过程中发生这种情况,则可能不应引发异常(因为这不是异常行为)。
简短版:使用异常处理异常行为,而不是处理程序中的正常控制流。
阿兰
#22楼
例外应该是例外 。 如果可以返回null ,则返回null 。
#23楼
例外与按合同设计有关。
对象的接口实际上是两个对象之间的契约,调用者必须满足该契约,否则接收者可能会因异常而失败。 有两种可能的合同
1)所有输入的方法均有效,在这种情况下,当找不到对象时必须返回null。
2)仅某些输入有效,即导致找到对象的输入。 在这种情况下,您必须提供第二种方法,允许调用者确定其输入是否正确。 例如
is_present(key)
find(key) throws Exception
如果并且仅当您提供第二个合同的两种方法时,您才可以抛出异常,因为找不到任何东西!
#24楼
这里还有更多建议。
如果返回一个集合,请避免返回null,而返回一个空集合,这会使枚举更容易处理,而无需先执行null检查。
多个.NET API使用thrownOnError参数的模式,该模式使调用者可以选择是否找到对象是否真的是例外情况。 Type.GetType就是一个例子。 BCL的另一个常见模式是TryGet模式,其中返回一个布尔值,并且该值通过输出参数传递。
在某些情况下,您还可以考虑使用Null Object模式,该模式可以是默认行为,也可以是没有行为的版本。 关键是避免在整个代码库中进行空检查。 有关更多信息,请参见此处http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx
#25楼
如果您使用的是引发异常的库或其他类,则应将其重新抛出 。 这是一个例子。 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 objectExample2 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\"");}}
#26楼
我只是想概括一下前面提到的选项,并在其中添加一些新选项:
- 返回null
- 抛出异常
- 使用空对象模式
- 为您的方法提供布尔参数,以便调用者可以选择是否要引发异常
- 提供一个额外的参数,以便调用者可以设置一个值,如果找不到值,他将返回该值
或者您可以结合使用以下选项:
提供您的getter的多个重载版本,以便调用者可以决定要走的路。 在大多数情况下,只有第一个具有搜索算法的实现,而其他仅包含第一个:
Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);
即使您选择仅提供一个实现,也可能希望使用类似的命名约定来阐明您的合同,并且如果您决定还添加其他实现,则它可以帮助您。
您不应过度使用它,但它可能会有所帮助,尤其是在编写一个将在具有许多不同错误处理约定的数百个不同应用程序中使用的助手类时。
#27楼
仅仅指的是null不被认为是一种异常行为的情况,我肯定是使用try方法的,很明显,不需要像这里所说的那样“看书”或“在飞跃之前先看一下”
所以基本上:
bool TryFindObject(RequestParam request, out ResponseParam response)
这意味着用户的代码也将很清楚
...
if(TryFindObject(request, out response)
{handleSuccess(response)
}
else
{handleFailure()
}
...
#28楼
首选返回null-
如果调用者不经检查就使用它,则无论如何都会发生异常。
如果呼叫者没有真正使用它,请不要向他征税try
/ catch
块
#29楼
不幸的是,JDK是不一致的,如果您尝试访问资源束中不存在的键,则不会发现异常,并且当您从map请求值时,如果不存在该值,则会得到null。 因此,如果发现的值可以为null,则将优胜者答案更改为以下内容,如果找不到则引发异常,否则返回null。 因此,请遵循带有一个例外的规则,如果您需要知道为什么找不到值,请始终提出例外,或者。
#30楼
引发异常的优点:
- 您的调用代码中的控制程序更简洁。 检查是否为空会注入条件分支,该分支由try / catch本地处理。 检查null并不表示您要检查的是什么-您是否正在检查null是因为您正在寻找期望的错误,还是正在检查null,因此您不会在下链进一步传递它?
- 消除了“ null”的含义的歧义。 null代表错误还是null实际存储在值中? 很难说何时只有一件事可以基于这种决心。
- 改进了应用程序中方法行为之间的一致性。 异常通常在方法签名中公开,因此您更能够理解应用程序中方法所占的优势,以及应用程序可以以可预测的方式对哪些信息作出反应。
有关示例的更多说明,请参见: http : //metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/
检索方法应该返回#39;null#39;还是无法产生返回值时引发异常? [关闭]相关推荐
- 扩展方法where方法查询不到数据,不会抛异常,也不是返回的null
如题,"扩展方法where方法查询不到数据,不会抛异常,也不是返回的null",示例代码如下: Product类: public class Product{private str ...
- [react] render方法的原理你有了解吗?它返回的数据类型是什么?
[react] render方法的原理你有了解吗?它返回的数据类型是什么? render的第一个参数通过babel转为React.createElement,后者根据参数类型的不同调用不同的内部方法来 ...
- android 按钮点击返回顶部,微信浏览器点击系统返回,安卓返回会重载页面回到页面顶部,iOS则返回则会保留之前浏览位置的解决方法...
后续补我框好串端题近还架比作和和近还架比作和和充: 页面css设置了height: 100%,来避免使用fixed定位弹窗引起的部分机型兼容问题,因此会在返回的时候回到页面顶部,补充解决办法: 在弹窗 ...
- [检索方法]——USPTO美国专利及商标局(1)
最近正好需要查阅些美国专利,然后发现官方的专利检索与我们熟知的传统检索方式不一样,最开始也没有看官方说明,所以越搜越离谱.最后狠下心来,以官方说明为主,化繁为简整理了一下基础的检索方法和缩略词介绍.希 ...
- mysql中avg函数如果有空值_对于 AVG 函数,如果列中所有行的值都是 null,那么 AVG 函数返回的值是( )...
[判断题]偶联剂是具有某些特定基团的化合物,它能通过化学和物理的作用将两种性质差异很大,原本不易结合的材料较牢固地结合起来 [多选题]滑石粉的片状结构使得滑石粉填充塑料的某些性能得到较大的改善,可提高 ...
- 向量快速检索方法总结——KDtree/Balltree/Annoy/NSW/HNSW
文章目录 导语 线性扫描 KDTree 构造 检索 特点 BallTree 构造 检索 特点 Annoy 构造 检索 特点 NSW 构造 检索 HNSW 构造 查找 导语 为什么要用向量快速检索呢?因 ...
- 【模型检索】基于特征线条的三维模型检索方法
文章目录 一.概述 二.方法细节 1.较优视点集提取 2.渲染混合轮廓线视图 3.线条边缘特征提取 三.实验过程 1.实验设置 2.验证 **较优视点集提取验证:** 结果 对比试验 一.概述 为了避 ...
- android 9.0室内定位方案,Android GPS室内定位问题的解决方法(location为null)
为什么室内没有location呢? 因为我们开发的时候几乎肯定都是在室内的,这个时候卫星你是搜索不到的,所以必然是定位不了的,所以系统如何将位置信息通知给你的程序.所以要从根本上解决这个问题,就要解决 ...
- 如何解决:“ UnicodeDecodeError:#39;ascii#39;编解码器无法解码字节”
本文翻译自:How to fix: "UnicodeDecodeError: 'ascii' codec can't decode byte" as3:~/ngokevin-sit ...
最新文章
- 云计算之路-阿里云上:消灭“黑色n秒”第一招——不让CPU空闲
- Hyper-V 的导入和导出
- 我凭什么拿到了阿里、腾讯、今日头条3家大厂offer?这原因我服了
- 我做的两个游戏的免CD补丁
- JVM&NIO&HashMap简单问
- Django项目实践2 - Django模板(view-html)
- RubyOnRails 文件下载
- topaz remask破解版|topaz remask抠图神器5破解版下载
- w8系统服务器垃圾清理,win8系统盘太大怎么办?来给TA瘦身吧! | SDT技术网
- 我们雇佣了一只大猴子
- 二本机械毕业2年,从外包ETL到大厂数据开发,月薪13K到年薪40W
- 基于E4A的蓝牙APP
- 探索 ES8 Object.entries()
- Resnet18卷积神经网络实现图片分类算法(代码全注释)
- mbr linux安装分区格式,装机、做系统必备:秒懂MBR和GPT分区表
- C2: 宽基窄基 场内场外
- 基于UMa和RMa传播模型的5G覆盖性能研究
- 尚硅谷 宋红康 JVM教程_01_内存与垃圾回收篇——02
- python画中国人口变化情况以及数据拟合
- 由于下列原因,安装程序无法继续microsoft office 2016 需要通用CRT(KB2999226)
热门文章
- RabbitMQ消息队列:发布/订阅(Publish/Subscribe)
- 网络安全系列之五十四 为GRUB引导菜单设置密码
- 保监会:关于开展2012年保险业信息系统安全检查工作的通知
- 你的关注,就是我的动力!(第3次改版中)
- 【[USACO13NOV]没有找零No Change】
- Sqoop导入HBase,并借助Coprocessor协处理器同步索引到ES
- SyntaxError: Missing parentheses in call to 'print' 这个错误原因是Python版本问题
- SpringMvc之参数绑定注解详解之一
- 计算数字1至10的总和
- Ubuntu 20.04更新源报错W: 校验数字签名时出错。此仓库未被更新,所以仍然使用此前的索引文件。