我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
我使用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