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

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

当前回答

使用Java8,您可以将供应商传递给下面这样的助手方法,

if(CommonUtil.resolve(()-> a.b().c()).isPresent()) {

}

上面的代码替换了下面的锅炉板代码,

if(a!=null && a.b()!=null && a.b().c()!=null) {

}

//通用工具.java

 public static <T> Optional<T> resolve(Supplier<T> resolver) {
        try {
            T result = resolver.get();
            return Optional.ofNullable(result);
        } catch (NullPointerException var2) {
            return Optional.empty();
        }
    }

其他回答

如果不允许空值

如果从外部调用方法,请从以下内容开始:

public void method(Object object) {
  if (object == null) {
    throw new IllegalArgumentException("...");
  }

然后,在该方法的其余部分中,您将知道该对象不为空。

如果它是一个内部方法(不是API的一部分),只需记录它不能为空,就可以了。

例子:

public String getFirst3Chars(String text) {
  return text.subString(0, 3);
}

但是,如果您的方法只是传递值,而下一个方法传递值等,则可能会出现问题。在这种情况下,您可能需要检查上述参数。

如果允许为空

这真的取决于。如果发现我经常这样做:

if (object == null) {
  // something
} else {
  // something else
}

所以我分支,做两件完全不同的事情。没有难看的代码片段,因为我确实需要根据数据做两件不同的事情。例如,我应该处理输入,还是应该计算一个好的默认值?


实际上,我很少使用“if(object!=null&&…”这个成语。

如果你展示了你通常使用这个习语的例子,那么给你举例可能会更容易。

您可以为对象和字符串创建一个通用方法,以便在应用程序中完全使用它-这可以帮助您和您的同事:创建一个类,例如StringUtilities,并添加方法,例如getNullString

public static String getNullString(Object someobject)
{
   if(null==someobject )
        return null;

   else if(someobject.getClass().isInstance("") && 
          (((String)someobject).trim().equalsIgnoreCase("null")|| 
          ((String)someobject).trim().equalsIgnoreCase("")))
        return null;

   else if(someobject.getClass().isInstance(""))
        return (String)someobject;

   else
        return someobject.toString().trim();
}

简单地将此方法称为,

if (StringUtilities.getNullString(someobject) != null)
{ 
  //Do something
}

我高度无视建议在任何情况下使用空对象的答案。这种模式可能会破坏合同,将问题埋得越来越深,而不是解决问题,更不用说使用不当会产生另一堆需要未来维护的样板代码。

实际上,如果从方法返回的某个值可以为空,并且调用代码必须对此做出决定,那么应该有一个更早的调用来确保状态。

还请记住,如果不小心使用,空对象模式将占用内存。为此,NullObject的实例应该在所有者之间共享,而不是每个所有者的unigue实例。

此外,我不建议在类型是原始类型表示的情况下使用这种模式,比如数学实体,它们不是标量:向量、矩阵、复数和POD(普通旧数据)对象,它们是用来以Java内置类型的形式保存状态的。在后一种情况下,您将以任意结果调用getter方法。例如,NullPerson.getName()方法应该返回什么?

为了避免荒谬的结果,值得考虑这样的案例。

对于每个Java开发人员来说,这是一个非常常见的问题。因此,Java8中有官方支持来解决这些问题,而不会产生混乱的代码。

Java 8引入了Java.util.Optional<T>。它是一个可以容纳或不容纳非空值的容器。Java8提供了一种更安全的方法来处理在某些情况下值可能为空的对象。它的灵感来自Haskell和Scala的想法。

简而言之,Optional类包含显式处理值存在或不存在的情况的方法。然而,与空引用相比,Optional<T>类的优点是,当值不存在时,强制您考虑情况。因此,可以防止意外的空指针异常。

在上面的示例中,我们有一个家庭服务工厂,它向家庭中可用的多个设备返回句柄。但这些服务可能可用或不可用;这意味着它可能会导致NullPointerException。与其在使用任何服务之前添加null if条件,不如将其包装到Optional<service>中。

包装到选项<T>

让我们考虑一种从工厂获取服务引用的方法。与其返回服务引用,不如用Optional包装它。它让API用户知道返回的服务可能不可用/不起作用,可以防御性地使用

public Optional<Service> getRefrigertorControl() {
      Service s = new  RefrigeratorService();
       //...
      return Optional.ofNullable(s);
   }

如您所见,Optional.Nullable()提供了一种简单的方式来包装引用。还有其他方法可以获取Optional的引用,Optional.empty()和Optional.of()。一种方法用于返回空对象而不是重新调整null,另一种方法分别包装不可为null的对象。

那么,如何避免空检查呢?

包装引用对象后,Optional提供了许多有用的方法来调用包装引用上的方法,而无需NPE。

Optional ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);

Optional.ifRepresent调用具有引用的给定Consumer(如果它是非空值)。否则,它什么也不做。

@FunctionalInterface
public interface Consumer<T>

表示接受单个输入参数但不返回结果的操作。与大多数其他功能界面不同,Consumer预期通过副作用进行操作。它很干净,很容易理解。在上面的代码示例中,如果Optional保持引用为非空,则调用HomeService.switchOn(Service)。

我们经常使用三元运算符来检查空条件,并返回替代值或默认值。可选提供了另一种处理相同条件而不检查null的方法。Optional.orElse(defaultObj)如果Optional具有空值,则返回defaultObj。让我们在示例代码中使用它:

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

现在HomeServices.get()做了同样的事情,但方式更好。它检查服务是否已初始化。如果是,则返回相同的或创建新的new服务。可选<T>。或Else(T)有助于返回默认值。

最后,这里是我们的NPE以及无空检查代码:

import java.util.Optional;
public class HomeServices {
    private static final int NOW = 0;
    private static Optional<HomeServices> service;

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

public Optional<Service> getRefrigertorControl() {
    Service s = new  RefrigeratorService();
    //...
    return Optional.ofNullable(s);
}

public static void main(String[] args) {
    /* Get Home Services handle */
    Optional<HomeServices> homeServices = HomeServices.get();
    if(homeServices != null) {
        Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl();
        refrigertorControl.ifPresent(HomeServices::switchItOn);
    }
}

public static void switchItOn(Service s){
         //...
    }
}

完整的帖子是NPE以及空检查免费代码…真的吗?。

对于Java8或更新版本,最好的选择可能是使用Optional类。

Optional stringToUse = Optional.of("optional is there");
stringToUse.ifPresent(System.out::println);

这对于可能的空值的长链来说尤其方便。例子:

Optional<Integer> i = Optional.ofNullable(wsObject.getFoo())
    .map(f -> f.getBar())
    .map(b -> b.getBaz())
    .map(b -> b.getInt());

如何在null上引发异常的示例:

Optional optionalCarNull = Optional.ofNullable(someNull);
optionalCarNull.orElseThrow(IllegalStateException::new);

Java7引入了Objects.requireOnNull方法,当需要检查某些内容是否为非空时,该方法非常方便。例子:

String lowerVal = Objects.requireNonNull(someVar, "input cannot be null or empty").toLowerCase();