我使用 x != null
来避免 NullPointerException
。有其他的替代方法吗?
if (x != null) {
// ...
}
我使用 x != null
来避免 NullPointerException
。有其他的替代方法吗?
if (x != null) {
// ...
}
Guava是谷歌提供的非常实用的核心库,它有一个漂亮且实用的API来避免null值。我发现UsingAndAvoidingNullExplained非常有帮助。
正如维基中所解释的:
Optional<T>
是一种用非空值替换可为空的T引用的方式。Optional可能包含非空的T引用(这种情况下我们说引用“存在”),也可能不包含任何内容(这种情况下我们说引用“不存在”)。从不说它“包含null”。
用法:
Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
java.util.Optional<T>
。它是一个容器,可能包含或不包含非空值。Java 8为处理对象在某些情况下可能为空的更安全方式提供了一种方法。它受到Haskell和Scala的启发。public Optional<Service> getRefrigertorControl() {
Service s = new RefrigeratorService();
//...
return Optional.ofNullable(s);
}
Optional.ofNullable()
提供了一种轻松获取包装引用的方式。还有另外两种获取Optional引用的方式,分别是Optional.empty()
和Optional.of()
。前者返回一个空对象而不是null,后者用于包装非空对象。Optional ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);
Optional.ifPresent会在参考值非空时使用给定的Consumer。否则,它将不执行任何操作。
@FunctionalInterface
public interface Consumer<T>
public static Optional<HomeServices> get() {
service = Optional.of(service.orElse(new HomeServices()));
return service;
}
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以及无需空值检查的代码……真的吗?。
if(homeServices != null) {
,可以改为 homeServices.ifPresent(h -> //action)
; - KrishPrabakar我喜欢Nat Pryce的文章。以下是链接:
文章中还有一个链接到Java Maybe类型的Git存储库,我觉得很有趣,但我认为它本身不能降低检查代码膨胀。在互联网上进行了一些研究后,我认为通过谨慎设计可以主要减少!= null代码膨胀。
我尝试了NullObjectPattern
,但对我来说并不总是最好的选择。有时候“无操作”是不合适的。
NullPointerException
是一个运行时异常,这意味着它是开发人员的错,并且通过足够的经验可以告诉你错误出在哪里。
现在来到答案:
尽可能将所有属性及其访问器设置为私有或完全避免将它们暴露给客户端。当然,您可以在构造函数中拥有参数值,但通过减少作用域,您不会让客户类传递无效值。如果需要修改值,则可以创建一个新的object
。您仅在构造函数中检查值一次,在其他方法中,几乎可以确定值不为空。
当然,要理解和应用此建议,经验是更好的方式。
Byte!
对于Java 8或更新版本,最好的替代方案可能是使用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());
Optional optionalCarNull = Optional.ofNullable(someNull);
optionalCarNull.orElseThrow(IllegalStateException::new);
Objects.requireNonNull
方法,当需要检查非空性时,它会很方便。例如:String lowerVal = Objects.requireNonNull(someVar, "input cannot be null or empty").toLowerCase();
if(object == null){
//you called my method badly!
}
或者
if(str.length() == 0){
//you called my method badly again!
}
getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)
public class Car {
@NotNull
private String manufacturer;
@NotNull
@Size(min = 2, max = 14)
private String licensePlate;
@Min(2)
private int seatCount;
// ...
}
我强烈反对建议在任何情况下都使用null对象。这种模式可能会破坏协议并将问题深埋,而不是解决它们,更不用说不当使用会创建另一堆需要未来维护的样板代码。
实际上,如果从方法返回的内容可能为null并且调用代码必须对其进行决策,则应该有一个早期调用来确保状态。
此外要记住,如果不小心使用null对象模式会消耗大量内存。因此,NullObject的实例应该在所有者之间共享,而不是每个所有者拥有一个唯一实例。
此外,我不建议在类型旨在表示原始类型 - 如数学实体,这些实体不是标量:向量、矩阵、复数和POD(Plain Old Data)对象,这些对象旨在以Java内置类型的形式保存状态时使用此模式。在后一种情况下,您将最终调用具有任意结果的getter方法。例如,NullPerson.getName()方法应该返回什么?
值得考虑这种情况以避免荒谬的结果。
在自己的代码中这样做,就可以避免!=null的检查。
大多数情况下,null检查似乎是为了保护对集合或数组的循环,因此只需将它们初始化为空,您将不需要任何null检查。
// Bad
ArrayList<String> lemmings;
String[] names;
void checkLemmings() {
if (lemmings != null) for(lemming: lemmings) {
// do something
}
}
// Good
ArrayList<String> lemmings = new ArrayList<String>();
String[] names = {};
void checkLemmings() {
for(lemming: lemmings) {
// do something
}
}
虽然有一点点额外的开销,但为了更干净的代码和更少的NullPointerExceptions,这是值得的。
org.apache.commons.lang.Validate //using apache framework
notNull(Object object, String message)
方法2:
if(someObject!=null){ // simply checking against null
}
方法三:
@isNull @Nullable // using annotation based validation
方法四:
// by writing static method and calling it across whereever we needed to check the validation
static <T> T isNull(someObject e){
if(e == null){
throw new NullPointerException();
}
return e;
}
Objects.requireNonNull()
已经涵盖了它。 - fozzybear总之,为了避免声明。
if (object != null) {
....
}
自Java 7起,您可以使用Objects
方法:
Objects.isNull(object)
Objects.nonNull(object)
Objects.requireNonNull(object)
Objects.equals(object1, object2)
自Java 8起,您可以使用Optional类(何时使用)
object.ifPresent(obj -> ...);
Java 8
object.ifPresentOrElse(obj -> ..., () -> ...);
Java 9
依赖于方法契约(JSR 305),并使用Find Bugs。使用注释@javax.annotation.Nullable
和@javax.annotation.Nonnnul
标记代码。同时可用Preconditions。
Preconditions.checkNotNull(object);
在特殊情况下(例如对于字符串和集合),您可以使用apache-commons(或Google guava)的实用程序方法:
public static boolean isEmpty(CharSequence cs) //apache CollectionUtils
public static boolean isEmpty(Collection coll) //apache StringUtils
public static boolean isEmpty(Map map) //apache MapUtils
public static boolean isNullOrEmpty(@Nullable String string) //Guava Strings
public static Object defaultIfNull(Object object, Object defaultValue)