异常被捕后返回null设计错误[关闭]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异常被捕后返回null设计错误[关闭]相关的知识,希望对你有一定的参考价值。
我总是遇到同样的问题,当在具有非void返回值的函数中捕获异常时,我不知道要返回什么。以下代码段说明了我的问题。
public Object getObject(){
try{
...
return object;
}
catch(Exception e){
//I have to return something here but what??
return null; // is this a bad design??
}
}
所以我的问题是:
- 返回null设计不好吗?
- 如果是这样,什么被视为更清洁的解决方案?
谢谢。
如果你真的无法处理它,我会说不要抓住异常。并且不会考虑记录处理错误。最好把它冒充给可以抛弃异常的人。
如果你必须返回一个值,并且null是唯一明智的东西,那就没有错。只需记录下来并向用户说明应该做什么。有一个单元测试,显示抛出的异常,所以开发人员可以看到你所接受的成语需要什么。它还将测试以确保您的代码在应该的时候抛出异常。
我会说这是一个不好的做法。如果收到null
,我怎么知道object
不存在或发生了一些错误?
我的建议是
如果写入的类型是数组或集合,则永远不会返回NULL。相反,返回一个空集合或一个空数组。
当返回类型是一个对象时,由您决定返回null,具体取决于方案。但永远不要吞下异常并返回NULL。
此外,如果在任何方案中返回NULL,请确保在方法中记录了这一点。
正如Josha Blooch在“Effective Java”一书中所说,null是Java的关键字。
这个词标识了一个没有指向任何其他内存位置的内存位置:在我看来,最好用关于功能域的行为分离进行编码(例如:你等待A类对象,但是你收到了类型B的对象)和低级域的行为(例如:内存不可用)。
在您的示例中,我将修改代码为:
public Object getObject(){
Object objectReturned=new Object();
try{
/**business logic*/
}
catch(Exception e){
//logging and eventual logic leaving the current ojbect (this) in a consistent state
}
return objectReturned;
}
缺点是在每次调用getObject()时都会创建一个完整的Object(然后在返回的对象不被读或写的情况下)。
但我更喜欢使用相同的对象而不是NullPointerException,因为有时这个异常很难修复。
关于如何处理例外的一些想法
- 返回null是好还是坏设计取决于异常以及此片段在系统中的放置位置。
- 如果Exception是NullPointerException,您可能会将catch块应用得有点突兀(作为流控制)。
- 如果它类似于IOException并且您无法对此进行任何操作,则应将Exception抛出到控制器。
- 如果控制器是组件的外观,则将异常转换为可能在接口处发生的详细记录的特定于组件的可能异常集。有关详细信息,您应将原始Exception包含为嵌套异常。
我总是遇到同样的问题,当在具有非void返回值的函数中捕获异常时,我不知道要返回什么。
如果您不知道要返回什么,那么这意味着您不知道如何处理异常。在那种情况下,重新抛出它。请不要悄悄地吞下它。并且,请不要返回null
,你不想强制代码的调用者写:
Foo foo = bar.getFoo();
if (foo != null) {
// do something with foo
}
这是恕我直言,一个糟糕的设计,我个人不喜欢写空检查(很多时候,使用null,而不是应该抛出异常)。
所以,正如我所说的,在方法中添加一个throws
子句,或者完全远程的try / catch块,或者如果有意义的话,保持try / catch(例如,如果你需要处理几个异常)并重新抛出异常。或将其包装在自定义异常中。
Related questions
最重要的是,我不想返回null。这是用户必须明确记住作为特殊情况处理的事情(除非他们期望为空 - 这是记录的)。如果他们很幸运,他们会立即尊重它并遭受错误。如果他们运气不好,他们会把它粘在一个集合中,以后会遇到同样的问题。
我想你有两个选择:
- 抛出一个例外。这样客户端必须以某种方式处理它(因此我要么记录它和/或检查它)。缺点是异常很慢并且不应该用于控制流程,因此我将此用于特殊情况(双关语)
- 你可以使用NullObject模式。
我遵循编码风格,我很少返回null。如果/当我这样做时,这是明确记录的,以便客户可以满足它。
例外表示特殊情况。假设你的代码应该返回一个对象,那么路上一定有问题(网络错误,内存不足,谁知道?)因此你不应该只是通过返回null来躲避它。
但是,在许多情况下,您可以在文档中看到方法在发生此类情况时返回null。然后该类的客户端可以依赖此行为并处理返回的null,没有什么不好的。在第二个用法示例中,请参见它不是一个例外情况 - 该类被设计为在某些条件下返回null - 因此这样做完全没问题(但是要记录这个预期的行为)。
因此,在一天结束时,它实际上取决于你是否因为某种特殊方式而无法返回物体,或者你根本没有物体返回,这绝对没问题。
控制器最终应始终捕获异常。 将<null>传递给控制器是没有意义的。 最好将原始异常抛出/返回堆栈。
我喜欢建议抛出异常的响应,但这意味着您已经将异常处理设计到了软件的体系结构中。
错误处理通常包含3个部分:检测,报告和恢复。根据我的经验,错误属于严重性类别(以下是缩写列表):
- 仅记录调试
- 暂停正在进行的操作并向用户报告,等待响应继续。
- 用辩护的对话框放弃并终止程序。
您的错误应该被分类,处理应尽可能一致和一致。如果每次编写新代码时都必须考虑如何处理每个错误,那么您的软件没有有效的错误处理策略。我希望有一个报告功能,如果继续取决于用户的选择,则启动用户交互。
关于是否返回null(一个陈旧的模式,如果我曾经看过一个)的答案取决于什么函数记录错误,如果函数失败并且返回null,调用者可以/必须做什么,以及是否不是错误的严重性决定了额外的处理。
这是你的代码,这是一个不错的解决方案。但是,如果你共享你的代码,你不应该使用它,因为它可能会抛出意外的异常(作为空指针一)。
你当然可以使用
public Object getObject() throws Exception {}
这可以给父母功能提供有用的信息,并会警告可能发生的事情。
基本上我会在Duffymo上同上,稍作补充:
正如他所说,如果您的调用者无法处理异常并恢复,那么请不要捕获异常。让更高级别的功能抓住它。
如果调用者需要做某事但应该适当地死掉,只需重新抛出异常即可。喜欢:
SomeObject doStuff()
throws PanicAbortException
{
try
{
int x=functionThatMightThrowException();
... whatever ...
return y;
}
catch (PanicAbortException panic)
{
cleanUpMess();
throw panic; // <-- rethrow the exception
}
}
您也可以重新打包例外,例如......
catch (PanicAbortException panic)
{
throw new MoreGenericException("In function xyz: "+panic.getMessage());
}
这就是为什么如此多的java代码与if (x!=null) {...}
子句膨胀。不要创建自己的Null Pointer Exceptions。
以上是关于异常被捕后返回null设计错误[关闭]的主要内容,如果未能解决你的问题,请参考以下文章
迁移到 AndroidX 后,findFragmentById 为片段返回 null
为啥我的云函数返回带有代码 INTERNAL 的异常,并且详细信息为 null 并带有未处理的错误 TypeError: is not a function