Java技术积累之Optional
简介
空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。
方法列表
静态方法
- static <t> Optional<t> empty():返回一个空Optional实例。</t></t>
- static <t> Optional<t> of(T value):返回Optional具有指定的当前非空值的。</t></t>
- static <t> Optional<t> ofNullable(T value):返回Optional描述指定值的描述,如果不为null,则返回null Optional。 </t></t>
实例方法
- boolean equals(Object obj):指示其他某个对象是否“等于”此Optional。
- Optional<t> filter(Predicate<? super T> predicate):如果存在一个值,并且该值与给定的谓词匹配,则返回一个Optional描述值的描述,否则返回一个empty Optional。</t>
- Optional flatMap(Function<? super T,Optional> mapper):如果存在值,则将提供的Optional-bearing映射函数应用于该值,返回该结果,否则返回empty Optional。
- T get():如果此值存在Optional,则返回该值,否则抛出NoSuchElementException。
- int hashCode():返回当前值的哈希码值(如果有),如果没有值,则返回0(零)。
- void ifPresent(Consumer<? super T> consumer):如果存在值,请使用该值调用指定的使用者,否则不执行任何操作。
- boolean isPresent():true如果存在值,则返回,否则返回false。
- Optional map(Function<? super T,? extends U> mapper):如果存在值,则将提供的映射函数应用于该值,如果结果为非null,则返回Optional描述结果的描述。
- T orElse(T other):返回值(如果存在),否则返回other。
- T orElseGet(Supplier<? extends T> other):返回值(如果存在),否则调用other并返回该调用的结果。
- <x extends="" throwable=""> T orElseThrow(Supplier<? extends X> exceptionSupplier):返回包含的值(如果存在),否则抛出异常,由提供的供应商创建。</x>
- String toString():返回此Optional的非空字符串表示形式,适用于调试。
使用建议
不推荐
- 调用 isPresent() 方法时
- 调用 get() 方法时
- Optional 类型作为类/实例属性时
- Optional 类型作为方法参数时
Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception. (调用 Optional.get() 前不事先用 isPresent() 检查值是否可用. 假如 Optional 不包含一个值, get() 将会抛出一个异常)
Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter. Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result”. Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not. (使用任何像 Optional 的类型作为字段或方法参数都是不可取的. Optional 只设计为类库方法的, 可明确表示可能无值情况下的返回类型. Optional 类型不可被序列化, 用作字段类型会出问题的)
推荐
使用Optional.Of(obj)
当明确将要传给Optional.of(obj)的obj参数不可能为null时, 比如它是一个刚new出来的对象(Optional.of(new User(...))), 或者是一个非null常量时;当想为obj断言不为null时, 即想在万一obj为null立即报告NullPointException异常, 立即修改, 而不是隐藏空指针异常时,就应该果断的用
Optional.of(obj)来构造Optional实例,而不让任何不可预计的null值有可乘之机隐身于Optional中。
避免使用isPresent()方法
// 存在即返回, 无则提供默认值 return user.orElse(null); //而不是 return user.isPresent() ? user.get() : null; return user.orElse(UNKNOWN_USER); // 存在即返回, 无则由函数来产生 return user.orElseGet(() -> fetchAUserFromDatabase()); //而不要 return user.isPresent() ? user: fetchAUserFromDatabase(); // 存在才对它做点什么 user.ifPresent(System.out::println);
使用map()
return user.map(u -> u.getOrders()).orElse(Collections.emptyList()) //上面避免Java 8之前的做法 if(user.isPresent()) { return user.get().getOrders(); } else { return Collections.emptyList(); } // map 是可能无限级联的, 比如再深一层 return user.map(u -> u.getUsername()) .map(name -> name.toUpperCase()) .orElse(null);