我使用x!=null以避免NullPointerException。还有其他选择吗?

if (x != null) {
    // ...
}

当前回答

如果您使用(或计划使用)JetBrains IntelliJ IDEA、Eclipse或Netbeans等Java IDE或findbugs等工具,那么您可以使用注释来解决这个问题。

基本上,你有@Nullable和@NotNull。

您可以在方法和参数中使用,如下所示:

@NotNull public static String helloWorld() {
    return "Hello World";
}

or

@Nullable public static String helloWorld() {
    return "Hello World";
}

第二个示例无法编译(在IntelliJ IDEA中)。

在另一段代码中使用第一个helloWorld()函数时:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

现在IntelliJ IDEA编译器将告诉您,检查是无用的,因为helloWorld()函数永远不会返回null。

使用参数

void someMethod(@NotNull someParameter) { }

如果你写的东西像:

someMethod(null);

这无法编译。

最后一个使用@Nullable的示例

@Nullable iWantToDestroyEverything() { return null; }

这样做

iWantToDestroyEverything().something();

你可以肯定这不会发生。:)

这是一个很好的方法,可以让编译器检查比通常更多的东西,并强制执行您的契约以使其更强大。不幸的是,并非所有编译器都支持它。

在IntelliJ IDEA 10.5及更高版本中,他们添加了对任何其他@Nullable@NotNull实现的支持。

查看博客文章更灵活和可配置的@Nullable/@NotNull注释。

其他回答

public class Null {

public static void main(String[] args) {
    String str1 = null;
    String str2 = "";

    if(isNullOrEmpty(str1))
        System.out.println("First string is null or empty.");
    else
        System.out.println("First string is not null or empty.");

    if(isNullOrEmpty(str2))
        System.out.println("Second string is null or empty.");
    else
        System.out.println("Second string is not null or empty.");
}

public static boolean isNullOrEmpty(String str) {
    if(str != null && !str.isEmpty())
        return false;
    return true;
}
}

输出

str1 is null or empty.
str2 is null or empty.

在上面的程序中,我们有两个字符串str1和str2。str1包含空值,str2为空字符串。

我们还创建了一个函数isNullOrEmpty(),顾名思义,它检查字符串是空还是空。它使用!=进行空检查null和字符串的isEmpty()方法。

简单地说,如果字符串不是null并且isEmpty()返回false,那么它既不是null也不是空的。否则,就是这样。

但是,如果字符串只包含空白字符(空格),则上述程序不会返回空。从技术上讲,isEmpty()看到它包含空格并返回false。对于带空格的字符串,我们使用string方法trim()来删除所有前导和尾随空格字符。

我可以更笼统地回答吗!

当方法以我们不期望的方式获取参数时,我们通常会遇到这个问题(错误的方法调用是程序员的错误)。例如:您希望得到一个对象,而得到一个null。您希望得到一个至少包含一个字符的字符串,而得到一个空字符串。。。

因此:

if(object == null){
   //you called my method badly!

}

or

if(str.length() == 0){
   //you called my method badly again!
}

他们都希望在执行任何其他函数之前确保我们收到了有效的参数。

如其他一些答案中所述,为了避免上述问题,您可以遵循契约设计模式。请参见http://en.wikipedia.org/wiki/Design_by_contract.

要在java中实现这种模式,可以使用javax.annotation.NotNull等核心java注释,或者使用Hibernate Validator等更复杂的库。

只是一个示例:

getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)

现在,您可以安全地开发方法的核心函数,而无需检查输入参数,它们可以保护您的方法不受意外参数的影响。

您可以更进一步,确保在应用程序中只能创建有效的pojo。(来自hibernate验证器站点的示例)

public class Car {

   @NotNull
   private String manufacturer;

   @NotNull
   @Size(min = 2, max = 14)
   private String licensePlate;

   @Min(2)
   private int seatCount;

   // ...
}

空对象模式可以用作此问题的解决方案。为此,应该修改someObject的类。

public abstract class SomeObject {
   public abstract boolean isNil();
}

public class NullObject extends SomeObject {
   @Override
   public boolean isNil() {
      return true;
   }
}
public class RealObject extends SomeObject {
   @Override
   public boolean isNil() {
      return false;
   }
}

现在先检查一下,

 if (someobject != null) {
    someobject.doCalc();
}

我们可以使用,

if (!someObject.isNil()) {
   someobject.doCalc();
}

参考:https://www.tutorialspoint.com/design_pattern/null_object_pattern.htm

您还可以使用CheckerFramework(带有JDK7及更高版本)静态检查空值。这可能会解决很多问题,但需要运行一个目前仅适用于OpenJDK AFAIK的额外工具。https://checkerframework.org/

通过遵循问题的大多数其他答案,您可以避免很多事情,以避免NullPointerException。我只想添加Java9中引入的其他一些方法,以优雅地处理这种情况,并展示一些旧的方法也可以使用,从而减少您的工作量。

公共静态布尔值isNull(对象obj)如果提供的引用为null,则返回true,否则返回错误。自Java 1.8以来公共静态布尔值nonNull(对象obj)如果提供的引用为非null,则返回true,否则返回错误。自Java 1.8以来公共静态<T>T requireOnNullElse​(T对象,T默认对象)如果第一个参数为非null,则返回第一个参数,否则返回非空的第二个参数。自Java 9以来公共静态<T>T requireOnNullElseGet​(T obj,供应商<?扩展T>供应商)如果第一个参数为非空,则返回第一个参数,否则返回supplier.get()的非空值。自Java 9以来公共静态<T>T requireOnNull​(T obj,供应商<字符串>消息供应商)检查指定的对象引用是否为空,否则将引发自定义的NullPointerException。自Java 1.8以来

有关上述功能的更多详细信息,请参阅此处。