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

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

当前回答

在Java中避免空检查的最佳方法是正确处理和使用异常。在我的经验中,随着您向前端移动,空检查变得越来越常见和必要,因为它更接近于通过UI提供无效信息的用户(例如,没有值,为字段提交)。

有人可能会争辩说,你应该能够控制UI正在做什么,以免你忘记大多数UI是通过某种类型的第三方库完成的,例如,根据情况或库的不同,它可能会为空白文本框返回NULL或空字符串。

您可以这样组合这两者:

try
{
  myvar = get_user_supplied_value(); 
  if (myvar == null || myvar.length() == 0) { alert_the_user_somehow(); return; };

  process_user_input(myvar);
} catch (Exception ex) {
  handle_exception(ex);
}

人们采取的另一种方法是:

if (myvar && myvar.length() > 0)  { };

你也可以抛出一个异常(这是我更喜欢的)

if (myvar == null || myvar.length() == 0) {
 throw new Exception("You must supply a name!");
};

但这取决于你。

其他回答

您可以考虑空对象是bug的情况,而不是空对象模式(有其用途)。

当抛出异常时,检查堆栈跟踪并解决错误。

对于每个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以及空检查免费代码…真的吗?。

我更喜欢这个

public void simpleFunc(SomeObject someObject){
    someObject = someObject != null ? someObject : new SomeObject(null);
    someObject.doSomething();
}

当然,在我的示例中,SomeObject优雅地处理空参数。例如,记录这样的事件,不做任何其他操作。

还有一种选择:

下面的简单函数有助于隐藏空检查(我不知道为什么,但我没有发现它是同一个公共库的一部分):

public static <T> boolean isNull(T argument) {
    return (argument == null);
}

你现在可以写了

if (!isNull(someobject)) {
    someobject.doCalc();
}

这是IMO更好的表达方式!=无效的

如果您认为对象不应为空(或是错误),请使用断言。如果您的方法不接受null参数,请在javadoc中说它并使用断言。

您必须检查对象!=仅当您想处理对象可能为空的情况时才为空。。。

有人建议在Java7中添加新注释,以帮助处理null/notnull参数:http://tech.puredanger.com/java7/#jsr308