使用Java8的新特性 Optional 代替 if - else 解决空指针问题
静态构造方法
JDK提供三个静态方法来构造一个`Optional`
public final class Optional<T> {
private static final Optional<?> EMPTY = new Optional<>();
private final T value;
// 该方法用来构造一个空的 Optional,如果 Optional 中的 value 为 null 则该 Optional 为不包含值的状态
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
// 通过一个非 null 的 value 来构造一个 Optional,
// 返回的 Optional 包含了 value 这个值。对于该方法,传入的参数一定不能为 null,否则便会抛出 NullPointerException
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
// 该方法和 of 方法的区别在于,传入的参数可以为 null,如果为 null 的话,返回的就是 Optional.empty()
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
}
常用方法
isPresent() / ifPresent()
// 如果值存在返回true,否则返回false
public boolean isPresent() {
return value != null;
}
// 如果Optional实例有值则为其调用consumer ,否则不做处理。
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
测试
public class OptionalTest {
public static void main(String[] args) {
User user = new User();
Optional<User> optional = Optional.ofNullable(user);
optional.ifPresent(s -> System.out.println(s));
}
}
Get()
获取Optional中的值,这个值也就是我们的值,Optional相当于就是一个外壳。
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
orElse() / orElseGet() / orElseThrow()
// 如果Optional中的值不为空,则返回Optional中的值,如果为空,则返回other值,
public T orElse(T other) {
return value != null ? value : other;
}
// 如果Optional中存在值,则返回值,否则返回other调用的结果
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
// 如果Optional中的值存在,则返回值,值不存在,则抛出异常函数Supplier中的异常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
测试
String value = "2";
String orElse = Optional.ofNullable(value).orElse("1");
System.out.println(orElse); //2
String value = null;
String orElse = Optional.ofNullable(value).orElse("1");
System.out.println(orElse); //1
-------------------------------------------------------
public class OptionalTest {
public static void main(String[] args) {
String value = null;
String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get);
System.out.println(orElse); // 123
String value = "2";
String orElse = Optional.ofNullable(value).orElseGet(OptionalTest::get);
System.out.println(orElse); // 2
}
public static String get(){
return "123";
}
}
-------------------------------------------------------
public class OptionalTest {
public static void main(String[] args) {
String value = null;
String orElse = Optional.ofNullable(value).orElseThrow(() -> new RuntimeException("不存在值"));
System.out.println(orElse);
}
}
map() / flatMap()
-
map(Function)
:如果 Optional 不为空,应用 Function 于 Optional 中的内容,并返回结果。否则直接返回 Optional.empty。 -
flatMap(Function)
:同map()
,但是提供的映射函数将结果包装在 Optional 对象中,因此flatMap()
不会在最后进行任何包装。
以上方法都不适用于数值型 Optional。一般来说,流的 filter()
会在 Predicate 返回 false
时移除流元素。而 Optional.filter()
在失败时不会删除 Optional,而是将其保留下来,并转化为空。
// 将Optional中的值作为参数传递到map中,如果传入的值为空,则返回一空的Optional对象,相当于Optional.empty(),
// 如果不为空,我们可以返回一个可以描述描述结果的返回值(Optional中的值,这个值可以重新赋值)
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
// 如果Optional中值存在,那么返回一个基于Optional的值(如Optional),
// 如果Optional中的值不存在,则返回一空的Optional对象,相当于Optional.empty(),
// 与map不同, map返回的是一个值,而flatMap返回一个基于Optional的值
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
测试
public class OptionalTest {
public static void main(String[] args) {
User user = null;
Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);
System.out.println(optional); //Optional.empty
User user = new User();
user.setUsername("Admin");
Optional<String> optional = Optional.ofNullable(user).map(OptionalTest::getMap);
System.out.println(optional); // Optional[Admin]
}
public static String getMap(User user){
return user.getUsername();
}
-------------------------------------------------------
User user = new User();
user.setUsername("Admin");
Optional<String> optional = Optional.ofNullable(user).flatMap(OptionalTest::getFlatMap);
System.out.println(optional);
}
public static Optional<String> getFlatMap(User user){
return Optional.ofNullable(user).map(User::getUsername);
}
filter()
将Optional中的值作为参数传入,如果符合规则,那么返回一个Optional对象,否则返回一个空的Optional 对象(Optional.empty)
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
实战
ifPresent(),这是一个终端操作,如果value存在则会调用指定的消费方法
// 获取 book 的值,若 book 为 null 则返回默认值
String book = Optional.ofNullable(person).map(Person::getBook).orElse("default");
// person 不为 null 则打印薪水
Optional.ofNullable(person).ifPresent(p -> System.out.println(p.getSalary()));
// 若 book 为 null,则设置默认值
Optional.ofNullable(person)
.map(Person::getComputer)
.ifPresent(c -> c.setBrandName("default name"));
Optional.ofNullable(person)
.map(Person::getComputer)
.ifPresent(this::consumerTest);
public void consumerTest(Computer computer){
System.out.println("consumer test");
System.out.println(computer);
}
// 获取brand,若 brandName 为 "",则抛出异常
// 因为 map只能过滤掉 null 值,而在工作中通常还需要做其它的判断,所以我们可以使用 map 去解析实体类中的某个属性,然后使用 filter 进行对应的过滤
String brand = Optional.ofNullable(person)
.map(Person::getComputer)
.map(Computer::getBrandName)
.filter(b -> !b.equals(""))
.orElseThrow(() -> new NumberFormatException("品牌为空"));
System.out.println("brand: " + brand);
参考文献: