当前位置: 首页 > 知识库问答 >
问题:

为什么我们需要检查对象是否为空?

范俊逸
2023-03-14

假设我在程序中有一段代码:

MyMessage message = getMessage(id); // call getMessage to return a message object
message.getUserId();

有人建议我在调用消息之前检查消息的空值。getUserId()。

检查null有两种方法:第一种:

MyMessage message = getMessage(id); // call getMessage to return a message object
if(message == null) {
   LOGGER.Error("message is null");
   return;
}
message.getUserId();

第二种方式:

MyMessage message = getMessage(id); // call getMessage to return a message object
if(message == null) {
   throw NullPointerException;
}
message.getUserId();

我的问题是:

  1. 哪种方式对null检查更好?返回还是抛出异常?
  2. 为什么我们在这里需要空检查?如果我们不这样做,那么message.getUserId();无论如何都会抛出NullPointerException

共有3个答案

柴凌
2023-03-14

是否需要考虑null的处理取决于getMessage()是否可以返回null。合同上怎么说?

如果您需要考虑它,那么正如您所说,有两种方法:显式检查和异常。但正如您自己所写,您为第二种情况编写的代码是多余的:

MyMessage message = getMessage(id);
if (message == null) {
   throw NullPointerException;
}
message.getUserId();

如果只使用null引用,将得到NullPointerException。虚拟机强制执行该操作。不要编写显式的check和throw,这只会使代码变得混乱。

MyMessage message = getMessage(id);
message.getUserId();

因此,您的选择实际上是:

>

让执行发生并在下栈的某个地方处理它。

这是一个系统设计问题。

师俊健
2023-03-14

这取决于你想要什么。然而,有一点是明确的:我们绝对不希望出现未经处理的运行时异常。

一种方法是检查对象是否为null,并为您的业务创建自定义异常,然后捕获此异常以执行业务或通知您的客户

public void yourMethod(){
    ...
    if(object == null){
      throw new CustomBusinessException("Object is null", object)
    }
    ...
 }
 
public void yourFirstCallMethod(){
    ...
    try{
        yourMethod()
    }catch(CustomBusinessException e){
        // do your business or inform client
    }
    ...
}

在此逻辑中,您可以详细说明您的异常,并且不会丢失其他异常,例如:

   try{
       yourMethod()
   }catch(CustomBusinessException e){
       // do your business or inform client
   }catch(CustomOtherBusinessException e){
       // do your business or inform client
   }catch(CustomAnotherBusinessException e){
       // do your business or inform client
   }catch(RuntimeException e){
       // if you really want to catch default exceptions, and make some different business to do.
   }catch(Exception e){
       // if you really want to catch all other exceptions.
   }

正如我所说,没有“真正的”或“严格的”方法来做到这一点。然而,在我看来,这是区分例外情况的好方法。

柯凯旋
2023-03-14

最好总是处理所有异常。对于用户来说,看到异常(以及它输出的所有堆栈跟踪)并不是特别愉快。以适当的方式显示清晰的消息,并明确检查可能导致异常的任何情况,这是一种可行的方法。然而,有一个例外(双关语):当从另一个方法调用该方法时,您需要特别了解出了什么问题,那么最好抛出一个带有适当消息的适当类型的异常,而不是返回字符串和进行其他恶作剧。

要直接回答您的问题:

>

  • 如果代码旨在直接向用户显示数据,第一种方式(以适当的方式显示清晰消息,显式检查可能导致异常的情况)更好。但是,如果数据要被计算机使用,第二种方式(抛出异常)更好。

    因为否则,那些正在阅读您的代码的人可能不会认为消息可以为null。此外,这不需要异常处理,因此没有人知道此方法可以引发异常。但是,当您显式检查null并显式抛出错误时,这需要将“throws”关键字添加到方法签名中,这需要通过调用该方法的任何程序来处理NullPointerException。

  •  类似资料:
    • 问题内容: Angular应用使用属性而不是事件。 为什么是这样? 问题答案: ng-click包含一个角度表达式。Angular表达式是在Angular 范围的上下文中求值的,该范围绑定到具有ng- click属性的元素或该元素的祖先。 Angular表达式语言不包含流控制语句,也不能声明变量或定义函数。这些限制意味着模板只能访问由控制器或指令提供的变量和运行功能。

    • 以我的拙见,关于“什么是单子”这个著名问题的答案,尤其是投票最多的答案,试图解释什么是单子,而没有明确解释为什么单子是真正必要的。它们能被解释为一个问题的解决方案吗?

    • 为什么我们需要字典? 计算机最适合使用数字,而人类最适合使用姓名。我们创建了DNS以便记住主机名而不是IP地址。字典以相同的方式使用,因此我们可以记住AVP名称而不是类型编号。当FreeRADIUS解析请求或生成响应时,会查阅字典。 但是,字典与DNS不同,因为RADIUS客户端不知道FreeRADIUS使用的这些“友好”名称。永远不会在RADIUS客户端和RADIUS服务器之间交换AVP名称。

    • 问题内容: 我开始使用RxJS,但我不明白为什么在此示例中我们需要使用类似or 的函数;数组的数组在哪里? 如果有人可以直观地解释正在发生的事情,那将非常有帮助。 问题答案: 当您有一个Observable的结果是更多Observable时,可以使用flatMap。 如果您有一个由另一个可观察对象产生的可观察对象,则您不能直接过滤,缩小或映射它,因为您有一个可观察对象而不是数据。如果您生成一个可观

    • 问题内容: 我对Maven快照的含义以及为什么要构建一个快照感到困惑。 问题答案: Maven中的快照版本尚未发布。 这个想法是,前一个版本(或任何其他版本)完成后,存在一个。那个版本可能会变成 。它基本上是“ 开发中”。这可能接近实际发行版,或相当遥远(0.9例如,发行后立即发行)。 “真实”版本和快照版本之间的区别在于快照可能会得到更新。这意味着今天下载的文件可能不同于昨天或明天下载的文件。

    • 问题内容: 有没有一种快速的方法来检查对象是jQuery对象还是本机JavaScript对象? 例: 显然,上面的代码有效,但并不安全。您可能会向对象添加选择器键并获得相同的结果。有没有更好的方法来确保该对象实际上是jQuery对象? 符合 问题答案: 您可以使用运算符: 说明 :该函数(又名)被实现为构造函数。构造函数将以前缀调用。 调用时,内部jQuery将此转换为1。JavaScript继续