当前位置: 首页 > 面试题库 >

Java:如何有效检查空指针

危晨
2023-03-14
问题内容

有一些模式可用于检查方法的参数是否已null赋值。

首先,经典的。在自制代码中很常见,并且很容易理解。

public void method1(String arg) {
  if (arg == null) {
    throw new NullPointerException("arg");
  }
}

其次,您可以使用现有框架。该代码看起来更好一些,因为它仅占用一行。缺点是它可能调用另一个方法,这 可能 会使代码的运行速度慢一些,具体取决于编译器。

public void method2(String arg) {
  Assert.notNull(arg, "arg");
}

第三,您可以尝试调用对对象没有副作用的方法。乍一看可能很奇怪,但它的令牌少于上述版本。

public void method3(String arg) {
  arg.getClass();
}

我还没有看到广泛使用的第三种模式,感觉就像我自己发明了这种模式。我喜欢它的简短性,因为编译器有很大的机会完全优化它或将其转换为一条机器指令。我还用行号信息编译我的代码,因此,如果NullPointerException抛出a,我可以将其追溯到确切的变量,因为每行只有一个这样的检查。

您喜欢哪种支票,为什么?


问题答案:

方法3:
arg.getClass();很聪明,但是除非这个习惯用法得到广泛采用,否则我宁愿使用更清晰,更详细的方法,而不是保存一些字符。我是“一次编写,多次阅读”的程序员。

其他方法是自记录文档:您可以使用一条日志消息来澄清发生了什么-在读取代码以及运行时都使用此日志消息。
arg.getClass()就目前而言,它不是自我记录。您至少可以使用注释或向代码审阅者澄清一下:

arg.getClass(); // null check

但是您仍然没有机会像使用其他方法一样在运行时中放置特定消息。

方法1与方法2(无效检查+ NPE / IAE与断言): 我尝试遵循以下准则:

http://data.opengeo.org/GEOT-290810-1755-708.pdf

  • 使用assert来检查私有方法的参数
    assert param > 0;

  • 使用null check +IllegalArgumentException检查公共方法上的参数
    if (param == null) throw new IllegalArgumentException("param cannot be null");

  • 在需要的地方使用null检查+ NullPointerException
    if (getChild() == null) throw new NullPointerException("node must have children");

但是
,由于这可能是有关如何null最有效地捕获潜在问题的问题,因此我不得不提及我的首选处理方法null是使用静态分析,例如,类型注释(例如,@NonNullla
JSR-305) 。我最喜欢的检查它们的工具是:

Checker框架:
Java的自定义可插入类型
https://checkerframework.org/manual/#checker-
guarantees

如果它是我的项目(例如,不是带有公共API的库),并且可以在整个过程中使用Checker Framework,则:

  • 我可以在API中更清楚地记录我的意图(例如,此参数可能不为null(默认值),但此参数可能为null(@Nullable;方法可能返回null;等等)。此注释恰好在声明中,而不是在Javadoc中更远的地方,因此更有可能得到维护。

  • 静态分析比任何运行时检查都有效

  • 静态分析将提前标记潜在的逻辑缺陷(例如,我试图将可能为null的变量传递给仅接受非null参数的方法),而不是取决于运行时发生的问题。

另外一个好处是,该工具允许我将注释放入注释中(例如`/ @Nullable
/),因此我的库代码可以与带类型注释的项目和非带类型注释的项目兼容(不是我可以使用任何这些项目)。

万一链接再次失效 ,这是《 GeoTools开发人员指南》中的部分:

http://data.opengeo.org/GEOT-290810-1755-708.pdf

5.1.7断言,IllegalArgumentException和NPE的使用

Java语言已经有两年了,现在可以使用assert关键字。此关键字可用于执行仅调试检查。尽管此功能有多种用途,但一种常见的用途是检查私有(而非公共)方法的方法参数。其他用途是后置条件和不变式。

参考:
断言编程

前提条件(例如私有方法中的参数检查)通常是断言的简单目标。后置条件和不变式有时不那么直率,但更有价值,因为非平凡条件有更多被破坏的风险。

  • 示例1: 在参考模块中进行地图投影之后,一个断言执行逆地图投影,并使用原始点(后置条件)检查结果。
  • 示例2: 在DirectPosition.equals(Object)实现中,如果结果为true,则该断言确保hashCode()与Object协定所要求的相同。

使用Assert检查私有方法上的参数

private double scale( int scaleDenominator ){
 assert scaleDenominator > 0;
 return 1 / (double) scaleDenominator;
}

您可以使用以下命令行参数启用断言:

java -ea MyApp

您只能使用以下命令行参数打开GeoTools断言:

java -ea:org.geotools MyApp

您可以禁用特定程序包的断言,如下所示:

java -ea:org.geotools -da:org.geotools.referencing MyApp

使用IllegalArgumentExceptions检查公共方法上的参数

严格禁止在公共方法上使用断言;因为所报告的错误是在客户端代码中造成的-
坦白地说,当他们搞砸了时​​,先用IllegalArgumentException告诉他们。

public double toScale( int scaleDenominator ){
 if( scaleDenominator > 0 ){
 throw new IllegalArgumentException( "scaleDenominator must be greater than 0");
 }
 return 1 / (double) scaleDenominator;
}

在需要的地方使用NullPointerException

如果可能,请执行自己的null检查;抛出IllegalArgumentException或NullPointerException,并提供有关发生问题的详细信息。

public double toScale( Integer scaleDenominator ){
 if( scaleDenominator == null ){
 throw new NullPointerException( "scaleDenominator must be provided");
 }
 if( scaleDenominator > 0 ){
 throw new IllegalArgumentException( "scaleDenominator must be greater than 0");
 }
 return 1 / (double) scaleDenominator;
}


 类似资料:
  • 问题内容: 检查URL在Java中是否有效的最佳方法是什么? 如果试着拨打和赶上,但它似乎很乐意与任何开头。 我不关心建立连接,只是有效性。有办法吗?Hibernate Validator中的注释?我应该使用正则表达式吗? 编辑:和 URL的一些示例。 问题答案: 考虑使用Apache Commons UrlValidator类 有几个属性,您可以设置来控制如何类的行为,在默认情况下,和被接受。

  • 下面的代码引发NullPointerException。即使有

  • 我定义了一个结构… 有时我给它分配一个空会话(因为不可能为零) 然后我想检查一下,如果它是空的: 显然这是行不通的。我怎么写?

  • 问题内容: 作为非终端操作,我如何检查a 是否为空,如果不是则抛出异常? 基本上,我在寻找与下面的代码等效的东西,但是没有在它们之间实现流。特别是,检查不应在终端操作实际消耗流之前进行。 问题答案: 如果您可以使用有限的并行功能,则以下解决方案将起作用: 这是一些使用它的示例代码: (有效的)并行执行的问题在于,支持对的拆分需要一种线程安全的方式来注意是否有任何片段以线程安全的方式看到了任何值。然

  • 问题内容: 我想知道此代码对于检查数组是否为空是否有效,还是应该检查null? 谢谢! 问题答案: 在数组类中,我们有一个定义为“ length”的静态变量,该变量保存数组对象中的元素数。您可以使用它来找到长度为:

  • 问题内容: 我有一个没有元素的数组,我正在尝试检查它是否为空。 例如,为什么下面代码中的if语句的条件永远不会为真? 问题答案: 数组和空数组之间有一个关键的区别。这是对的测试null。 “Empty”在这里没有官方含义。我选择将空定义为具有0个元素: 如果所有元素都是,则“空”的另一种定义是: 要么