我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
当前回答
首先,我们不能真正删除所有空条件。我们可以使用@NotNull和@Nullable注释来减少它们(如上所述)。但这需要一些框架的支持。这是OVal可以帮助的地方。
基本思想是对象/参数/构造函数应始终满足前提条件。您可以有很多先决条件,例如Nullable、NotNull和OVal。它们会注意对象在调用时应处于一致状态。
我猜OVal内部使用AspectJ来验证前提条件。
@Guarded
public class BusinessObject
{
public BusinessObject(@NotNull String name)
{
this.name = name;
}
...
}
例如
// Throws a ConstraintsViolatedException because parameter name is null
BusinessObject bo = new BusinessObject(null);
其他回答
对于每个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 lambdas中,可以定义以近乎完美的方式处理嵌套空检查的util方法。
void example() {
Entry entry = new Entry();
// This is the same as H-MANs solution
Person person = getNullsafe(entry, e -> e.getPerson());
// Get object in several steps
String givenName = getNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.getGivenName());
// Call void methods
doNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.nameIt());
}
/** Return result of call to f1 with o1 if it is non-null, otherwise return null. */
public static <R, T1> R getNullsafe(T1 o1, Function<T1, R> f1) {
if (o1 != null) return f1.apply(o1);
return null;
}
public static <R, T0, T1> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, R> f2) {
return getNullsafe(getNullsafe(o0, f1), f2);
}
public static <R, T0, T1, T2> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Function<T2, R> f3) {
return getNullsafe(getNullsafe(o0, f1, f2), f3);
}
/** Call consumer f1 with o1 if it is non-null, otherwise do nothing. */
public static <T1> void doNullsafe(T1 o1, Consumer<T1> f1) {
if (o1 != null) f1.accept(o1);
}
public static <T0, T1> void doNullsafe(T0 o0, Function<T0, T1> f1, Consumer<T1> f2) {
doNullsafe(getNullsafe(o0, f1), f2);
}
public static <T0, T1, T2> void doNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Consumer<T2> f3) {
doNullsafe(getNullsafe(o0, f1, f2), f3);
}
class Entry {
Person getPerson() { return null; }
}
class Person {
Name getName() { return null; }
}
class Name {
void nameIt() {}
String getGivenName() { return null; }
}
(这个答案首先发布在这里。)
我更喜欢这个
public void simpleFunc(SomeObject someObject){
someObject = someObject != null ? someObject : new SomeObject(null);
someObject.doSomething();
}
当然,在我的示例中,SomeObject优雅地处理空参数。例如,记录这样的事件,不做任何其他操作。
总而言之,避免声明
if (object != null) {
....
}
由于java7,您可以使用Objects方法:Objects.isNull(对象)Objects.nonNull(对象)Objects.requireOnNull(对象)Objects.equals(object1,object2)从java8开始,您可以使用Optional类(何时使用)
object.ifPresent(obj->…);java 8
object.ifPresentOrElse(对象->…,()->…);java 9
依靠方法契约(JSR305)并使用FindBugs。用annotations@javax.annotation.Nullable和@javax.annotation.Nonnnual标记代码。还提供了前提条件。前提条件.checkNotNull(对象);在特殊情况下(例如字符串和集合),可以使用apachecommons(或Google guava)实用程序方法:
公共静态布尔isEmpty(CharSequence cs)//apache CollectionUtils公共静态布尔isEmpty(集合coll)//apacheStringUtils公共静态布尔isEmpty(Map Map)//apache MapUtils公共静态布尔isNullOrEmpty(@Nullable String字符串)//Guava字符串
当您需要在null时分配默认值时,请使用apachecommons-lang
公共静态对象defaultIfNull(对象对象,对象defaultValue)
有时,您可以使用对其参数进行操作的方法来定义对称操作:
a.f(b); <-> b.f(a);
如果你知道b永远不可能为空,你可以交换它。它对equals最有用:而不是foo.equals(“bar”);最好使用“bar”。equals(foo);。