繁体   English   中英

检查 Java 中的 null 值的最佳方法是什么?

[英]Best way to check for null values in Java?

在调用 object 的 function 之前,我需要检查 object 是否为NullPointerException

go 关于这个的最佳方法是什么? 我考虑过这些方法。
Java的最佳编程实践是哪一个?

// Method 1
if (foo != null) {
    if (foo.bar()) {
        etc...
    }
}

// Method 2
if (foo != null ? foo.bar() : false) {
    etc...
}

// Method 3
try {
    if (foo.bar()) {
        etc...
    }
} catch (NullPointerException e) {
}

// Method 4 -- Would this work, or would it still call foo.bar()?
if (foo != null && foo.bar()) {
    etc...
}

方法4最好。

if(foo != null && foo.bar()) {
   someStuff();
}

将使用短路评估,这意味着如果logical AND的第一个条件为假,则结束。

最后一个也是最好的。 逻辑与

  if (foo != null && foo.bar()) {
    etc...
}

因为在逻辑&&

没有必要知道右手边是什么,结果一定是假的

喜欢阅读: Java逻辑运算符短路

在Java 8中,检查null的最佳方法是:

Objects.isNull(obj) //returns true if the object is null

Objects.nonNull(obj) //returns true if object is not-null

if(Objects.nonNull(foo) && foo.something()) // Uses short-circuit as well. No Null-pointer Exceptions are thrown.

除此之外......您还可以选择Guava的Optional Class

减少类似于(obj=null)的类型错误,它总是返回true如前面的答案所述。

  • 不要捕获NullPointerException 这是一种不好的做法。 最好确保该值不为空。
  • 方法#4 对你有用。 它不会评估第二个条件,因为 Java 有短路(即,如果后续条件不改变布尔表达式的最终结果,则不会评估它们)。 在这种情况下,如果逻辑 AND 的第一个表达式计算结果为 false,则不需要计算后续表达式。

方法 4 无疑是最好的,因为它清楚地表明会发生什么并且使用最少的代码。

方法 3 在各个层面上都是错误的。 您知道该项目可能为空,因此这不是特殊情况,您应该检查一下。

方法 2 只是使它比需要的更复杂。

方法 1 只是方法 4,多了一行代码。

Java 7 中,您可以使用Objects.requireNonNull() java.util添加Objects类的导入。

public class FooClass {
    //...
    public void acceptFoo(Foo obj) {
        //If obj is null, NPE is thrown
        Objects.requireNonNull(obj).bar(); //or better requireNonNull(obj, "obj is null");
    }
    //...
}

我会说方法 4 是我看过的代码中最通用的习惯用法。 但这对我来说总是有点臭。 它假定 foo == null 与 foo.bar() == false 相同。

这对我来说并不总是正确的。

方法 4 是我的首选方法。 && 运算符的短路使代码最具可读性。 方法 3,Catching NullPointerException,在大多数情况下是不赞成的,因为简单的 null 检查就足够了。

如果你控制被调用的 API,可以考虑使用Guava 的 Optional 类

更多信息在这里 更改您的方法以返回Optional<Boolean>而不是Boolean

通过调用Optional一种方便的方法,这会通知调用代码它必须考虑 null 的可能性

正如其他人所说,#4 是不使用库方法时的最佳方法。 但是,您应该始终将 null 放在比较的左侧,以确保在出现拼写错误时不会意外地将 null 分配给 foo。 在这种情况下,编译器会发现错误。

// You meant to do this
if(foo != null){

// But you made a typo like this which will always evaluate to true
if(foo = null)

// Do the comparison in this way
if(null != foo)

// So if you make the mistake in this way the compiler will catch it
if(null = foo){

// obviously the typo is less obvious when doing an equality comparison but it's a good habit either way
if(foo == null){
if(foo =  null){

您还可以使用StringUtils.isNoneEmpty("")来检查是否为 null 或为空。

如果你打算用双等号“==”检查,那么用对象引用检查 null 就像

if(null == obj) 

代替

if(obj == null)

因为如果你输入错误 single equal if(obj = null) 它将返回 true (分配对象返回成功(其值为 'true' )。

如果您无权访问 commons apache 库,则以下内容可能会正常工作

if(null != foo && foo.bar()) {
//do something
}

你最后的提议是最好的。

if (foo != null && foo.bar()) {
    etc...
}

因为:

  1. 阅读起来更容易。
  2. 这是安全的:如果 foo == null,则永远不会执行 foo.bar()。
  3. 它可以防止不良做法,例如捕获 NullPointerExceptions(大部分时间是由于代码中的错误)
  4. 它的执行速度应该与其他方法一样快甚至更快(尽管我认为几乎不可能注意到它)。

我们可以使用 Object 类的 Object.requireNonNull 静态方法。 实现如下

public void someMethod(SomeClass obj) {
    Objects.requireNonNull(obj, "Validation error, obj cannot be null");
}

简单的一行代码来检查 null :

namVar == null ? codTdoForNul() : codTdoForFul();

对于 java 11+,您可以使用Objects.nonNull(Object obj)

if(nonNull(foo)){ 
//
}
public <T, U> U defaultGet(T supplier, Function<T, U> mapper, U defaultValue) {
        return Optional.ofNullable(supplier).map(mapper).orElse(defaultValue);

    }

如果您喜欢函数编程,可以创建此函数

Java中处理空值的通用方法

  1. 如果该对象不为空,我们将执行以下操作。

    一种。 我们可以改变对象(I)

    我们可以返回 something(O) 作为输出而不是改变对象 (I)

    C。 我们可以同时做

在这种情况下,我们需要传递一个函数,该函数需要接受作为我们对象的输入 param(I) 如果我们这样接受,那么我们可以根据需要改变该对象。 而且该功能可能是(O)。

  1. 如果 object 为 null 那么我们将做以下事情

    一种。 我们可能会以自定义的方式抛出异常

    我们可能会返回一些东西。

在这种情况下,对象为 null,因此我们需要提供该值,否则我们可能需要抛出异常。

我举两个例子。

  1. 如果我想在字符串中执行修剪,那么该字符串不应为空。 在这种情况下,我们必须额外检查空值,否则我们会得到 NullPointerException
public String trimValue(String s){
   return s == null ? null : s.trim();
}
  1. 如果该对象不为空,我想为对象设置一个新值的另一个函数,否则我想抛出一个运行时异常。
public void setTeacherAge(Teacher teacher, int age){
   if (teacher != null){
      teacher.setAge(age);
   } else{
      throw new RuntimeException("teacher is null")
    }
}

在我的解释中,我创建了一个接受值(值可能为空)的通用方法,一个在对象不为空时将执行的函数,以及在对象为空时将执行的另一个供应商函数。

泛型函数

  public <I, O> O setNullCheckExecutor(I value, Function<I, O> nonNullExecutor, Supplier<O> nullExecutor) {
        return value != null ? nonNullExecutor.apply(value) : nullExecutor.get();
    }

所以有了这个通用函数后,我们可以对示例方法1进行如下操作。

//To Trim a value
        String trimmedValue = setNullCheckExecutor(value, String::trim, () -> null);

这里, nonNullExecutor 函数是修剪值(使用方法参考)。 nullExecutorFunction 将返回 null,因为它是一个标识函数。

2.

// mutate the object if not null otherwise throw a custom message runtime exception instead of NullPointerException
 setNullCheckExecutor(teacher, teacher -> {
            teacher.setAge(19);
            return null;
        }, () -> {
            throw new RuntimeException("Teacher is null");
        });

在处理 function 时,我经常寻找 null -

public static void doSomething(Object nullOrNestedObject) {
     if (nullOrNestedObject == null || nullOrNestedObject.getNestedObject()) {
        log.warn("Invalid argument !" );
        return;
        // Or throw an exception
        // throw new IllegalArgumentException("Invalid argument!");

     }
    nullOrNestedObject.getNestedObject().process()
     ... // Do other function stuff
}

这样,如果它是 null 它只会提前停止执行,并且您不必将所有逻辑嵌套在 if 中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM