在异常被捕获错设计后返回null

时间:2010-01-30 15:43:31

标签: java exception return-value

我总是遇到同样的问题,当在具有非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 bad design?
  • 如果是这样,什么被视为更清洁的解决方案??

感谢。

13 个答案:

答案 0 :(得分:48)

我会说如果你真的无法处理它,就不要抓住异常。并且不会考虑记录处理错误。最好把它冒充给可以抛弃异常的人。

如果你必须返回一个值,并且null是唯一明智的东西,那就没有错。只需记录下来并向用户说明应该做什么。有一个单元测试,显示抛出的异常,所以开发人员可以看到你所接受的成语需要什么。它还将测试以确保您的代码在应该的时候抛出异常。

答案 1 :(得分:26)

  

我总是遇到同样的问题,当在具有非void返回值的函数中捕获异常时,我不知道要返回什么。

如果您不知道要返回什么,那么这意味着您不知道如何处理异常。在这种情况下,重新抛出。请不要无声吞咽。并且,不返回null ,您不想强制代码的调用者写:

Foo foo = bar.getFoo();
if (foo != null) {
    // do something with foo
} 

这是恕我直言,一个糟糕的设计,我个人不喜欢写空检查(很多时候,使用null代替应该抛出异常)。

所以,正如我所说,在方法中添加一个throws子句,或者完全远程的try / catch块,或者如果有意义的话,保留try / catch(例如,如果你需要处理几个例外)并按原样重新抛出异常或将其包装在自定义异常中。

相关问题

答案 2 :(得分:7)

最重要的是我不想返回null。这是用户必须明确记住作为特殊情况处理的事情(除非他们期望为空 - 这是记录的)。如果他们很幸运,他们会立即尊重它并遭受错误。如果他们运气不好,他们会把它粘在一个集合中,以后会遇到同样的问题。

我认为你有两个选择:

  1. 抛出异常。这样客户端必须以某种方式处理它(因此我要么记录它和/或检查它)。缺点是异常缓慢且不应用于控制流程,因此我将此用于特殊情况(双关语)
  2. 您可以使用NullObject模式。
  3. 我遵循编码风格,我很少返回null。如果/当我这样做时,这是明确记录的,以便客户可以满足它。

答案 3 :(得分:5)

例外表示例外案例。假设你的代码应该返回一个对象,那么某些东西必须在路上出现错误(网络错误,内存不足,谁知道?)因此你不应该只是通过返回null来安静它。 / p>

但是,在许多情况下,您可以在文档中看到方法在发生此类情况时返回null。然后该类的客户端可以依赖此行为并处理返回的null,没有什么不好的。请参阅第二个用法示例,它不是一个例外情况 - 该类被设计为在某些条件下返回null - 因此这样做完全没问题(但是要记录这个预期的行为)。

因此,在一天结束时,这实际上取决于你是否因为某种特殊方式而无法返回物体,或者你根本没有物体返回,这绝对没问题。

答案 4 :(得分:2)

这是你的代码,这是一个不错的解决方案。但是如果你共享你的代码,你就不会使用它,因为它会抛出意外的异常(作为nullpointer)。

你当然可以使用

public Object getObject() throws Exception {}

可以为父功能提供可用的信息,并警告可能会发生不良事件。

答案 5 :(得分:2)

控制器最终应始终抓住例外情况 传递< null>直到控制器 毫无意义 最好将原始异常抛出/返回堆栈。

答案 6 :(得分:2)

我喜欢建议抛出异常的响应,但这意味着您已将异常处理设计到软件的体系结构中。

错误处理通常包含3个部分:检测,报告和恢复。根据我的经验,错误属于严重性类别(以下是缩写列表):

  • 仅供调试
  • 暂停正在进行的操作并向用户报告,等待响应继续。
  • 用抱歉的对话框放弃并终止程序。

您的错误应该被分类,处理应尽可能一致和一致。如果每次编写新代码时都必须考虑如何处理每个错误,那么您的软件没有有效的错误处理策略。我希望有一个报告功能,如果继续取决于用户的选择,则启动用户交互。

关于是否返回null(如果我曾经看过一个陈旧的模式)的答案取决于哪个函数记录错误,如果函数失败并返回null,调用者可以/必须做什么?以及错误的严重程度是否要求额外处理。

答案 7 :(得分:1)

关于如何处理例外的一些想法

  • 返回null是好还是坏设计取决于异常以及此片段在系统中的放置位置。

  • 如果Exception是NullPointerException,您可能会将catch块应用得有些突兀(作为流控制)。

  • 如果它类似于IOException并且您无法解决原因,则应将Exception抛出到控制器。

  • 如果控制器是组件的外观,则将异常转换为可能在接口上发生的详细记录的组件特定的可能异常集。有关详细信息,您应将原始Exception包含为嵌套异常。

答案 8 :(得分:1)

基本上我会在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());
}

答案 9 :(得分:1)

这就是为什么这么多java代码在if (x!=null) {...}子句中膨胀的原因。不要创建自己的Null Pointer Exceptions。

答案 10 :(得分:1)

正如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 ,因为有时这个异常很难解决。

答案 11 :(得分:1)

我会说这是一种不好的做法。如果收到null,我如何知道object是否存在或是否发生了错误?

答案 12 :(得分:1)

我的建议是

  如果写入的类型是数组或者,那么

永远不会返回NULL   采集。相反,返回一个空集合或一个空数组。

当返回类型是一个对象时,由您决定返回null,具体取决于方案。但永远不要吞下异常并返回NULL。

此外,如果您在任何方案中返回NULL,请确保方法中记录了这一点。