避免 "Potential null pointer access"

avoiding "Potential null pointer access"

在解决以下问题时,您认为哪个是最佳实践:

MyClass myVariable = null;
if ( ..condition 1.. ) {
  myVariable = new MyClass(1);
} else if ( ..condition 2.. ) {
  myVariable = new MyClass(2);
}

myVariable.execute();

哪个是解决警告的好方法?

  1. 一个整理else

    final MyClass myVariable;
    ....
    } else {
      // let's say this assert makes sense here
      Assert.fail("This should not happen");
    }
    
  2. RuntimeException

    final MyClass myVariable;
    ....
    } else {
      throw new RuntimeException("Some message, like <should not happen>");
    }
    
  3. 检查 NPE

    final MyClass myVariable;
    ....
    if (myVariable != null) {
      myVariable.execute();
    }
    
  4. 其他想法?

提前致谢!

下面更好。

final param;
if ( ..condition 1.. ) {
  param = 1;
} else if ( ..condition 2.. ) {
  param = 2;
} else {
   throw new IllegalArgumentException("no condition matches");
}

new MyClass(param).execute();

如果您的条件很简单,请尝试使用 switch-case 重写 if-else 链。这个比较好。

这取决于条件 1 或条件 2 是否必须始终为真。 如果条件 2 与条件 1 完全相反,您可以将 else if ( ..condition 2.. ) 替换为 else 并解决您的问题。

如果不是,并且条件 1 和条件 2 都为假的事实表明输入无效,我会抛出异常。

如果两个条件都为假的场景是有效场景,我会在调用 myVariable.execute().

之前检查 myVariable 是否为空

我会像您的第 3 个示例一样进行空值检查。如果您正在实现的功能是一个附加功能或可选的东西,当您的变量为 null 时,您可以忽略它。 但是,当你有一个主要功能,并且用户等待响应时,你应该给用户发消息,让他再试一次。

如果您始终可以初始化变量,请使用以 else:

结尾的 if-else
MyClass myClass;

if (...)
    myClass = new MyClass(1);
else if (...)
    myClass = new MyClass(2);
else if (...)
    ...
else
    myClass = new MyClass(n);

myClass.execute();

如果您不能总是初始化您的变量,并且您只想在初始化时使用该变量:

MyClass myClass;

if (...)
    myClass = new MyClass(1);
else if (...)
    myClass = new MyClass(2);
else if (...)
    ...

if (myClass != null)
    myClass.execute();

如果你不能总是初始化你的变量但它是必需的:

MyClass myClass;

if (...)
    myClass = new MyClass(1);
else if (...)
    myClass = new MyClass(2);
else if (...)
    ...
else
    throw new Exception(...);// or notify the user and exit

myClass.execute();

另一种方法是定义一个init()方法:

MyClass myClass = init(...);

// check if myClass is != null if init can return a null
myClass.execute();

MyClass init(...) {
    if (...)
        return new MyClass(1);
    else if (...)
        return new MyClass(2);
    else if (...)
        ...
    else
        return new MyClass(n);// or return null

总之,要看你是什么情况。

which would you say is the best practice when implementing the following problem

这取决于上下文:

  • 这取决于检查condition 1condition 2的(深层)目的。

  • 这取决于它们都为假意味着什么:

    • 是"normal"条件吗?

    • 是否是用户输入错误?

    • 调用此方法的代码中是否存在编程错误?

    • 是不是这段代码的编程错误;例如违反不变量?

    • 还有别的吗?

  • 这取决于您希望如何处理该案例。

据此,您提出的任何替代方案都可能是合适的。


... which would you say is the best practice ...

我不会用短语 "best practice" 来表示这样的事情。即使我知道上下文也不知道。每当我在问题中听到短语 "best practice" 时,我的印象是有人想要一个 "cookie cutter" 可以不假思索地应用的解决方案。

我在这里唯一要推荐的 "best practice" 是理解上下文,然后选择最合适的解决方案。

而且... "any solution that makes the warning go away" 不是正确的方法。