前言
在某些情况下,首先要判断某个参数或者某个方法的返回值是否为null,才能继续操作该参数。对于某些链式操作需要多次通过if语句判断是否为空,才能确保不抛出NullPointerException,这段非空判断的代码显得非常冗长和恶心。比如下面这段代码:
String isoCode = "default";
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
isocode = country.getIosCode();
if (isocode != null) {
isocode = isocode.toUpperCase();
}
}
}
}
在java 8里,JDK引入了一个Optional类,该类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。通过本文的学习,我们看下如何通过Optional类重写上面那段判空代码。
接下来,我们一起学习Optional类的初始化和它里面的方法。lambda表达式和四个基本函数式接口是本文的基础,可以通过 java8 -函数式编程之Lambda表达式 和 java8 -函数式编程之四个基本接口 充分了解。
Optional初始化
Optional类的构造方法是私有方法,所以只能通过它的静态工厂方法进行初始化。它的初始化方法有如下四种:
(1) <T> Optional<T> of (T value) :为非null的值创建一个Optional。如果传入参数为null,抛出NullPointerException。
//调用工厂方法创建Optional实例
Optional<String> name = Optional.of("hello");
//传入参数为null,抛出NullPointerException.
Optional<String> someNull = Optional.of(null);
(2)<T> Optional<T> ofNullable (T value) :为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。它和 of 的区别是可以传null值。在它的实现代码中,如果传的值为null,会调用另一个静态工厂方法 empty 获取一个Optional对象。
Optional empty = Optional.ofNullable(null);
(3)<T> Optional<T> empty () :ofNullable静态工厂方法,传null值时的实现,返回一个空的Optional。
Optional类的其它方法
(1)isPresent :如果值存在返回true,否则返回false。
// false
Optional<String> empty = Optional.ofNullable(null);
System.out.println(empty.isPresent());
// true
Optional<String> optionalS2 = Optional.of(s2);
System.out.println(optionalS2.isPresent());
(2)get:如果Optional有值则将其返回,否则抛出NoSuchElementException
//获取hello
Optional.of("hello").get();
//抛出NoSuchElementException
Optional.empty().get();
(3)void ifPresent (Consumer<? super T> consumer) :如果Optional实例有值则调用consumer,否则不做处理。
//调用ifPresent方法里面的consumer
Optional.of("hello")
.ifPresent(System.out::println);
(4)orElse:如果有值则将其返回,否则返回指定的其它值
//输出:null
System.out.println(Optional.empty().orElse("null"));
//输出:hello
System.out.println(Optional.of("hello").orElse("null"));
(5)T orElseGet (Supplier<? extends T> other) :orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受 Supplier接口 的实现用来生成默认值。
//输出null
System.out.println(Optional.empty().orElseGet(() -> "null"));
//输出hello
System.out.println(Optional.of("hello").orElseGet(() -> "null"));
(6)<X extends Throwable> T orElseThrow (Supplier<? extends X> exceptionSupplier) throws X :如果有值则将其返回,否则抛出supplier接口创建的异常。
//抛出exception
try {
Optional.empty().orElseThrow(()->new Exception("为空"));
} catch (Exception e) {
e.printStackTrace();
}
(7)<U> Optional<U> map (Function<? super T, ? extends U> mapper) :如果参数 mapper 有值,则调用map方法执行mapper参数的Function方法得到返回值。如果mapper的返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。如果传入的mapper参数是null,抛出NullPointerException。
//输出 JACK
Optional<String> stringOptional = Optional.of("jack").map((value) -> value.toUpperCase());
System.out.println(stringOptional.orElse("default"));
//输出 default
Optional<String> stringOptional1 = Optional.of("jack").map((value) -> null);
System.out.println(stringOptional1.orElse("default"));
//输出 default,并且不会调用mapper
String s2 = null;
Optional<String> stringOptional2 = Optional.ofNullable(s2).map((value) -> value.toUpperCase());
System.out.println(stringOptional2.orElse("default"));
//如果参数mapper为null,抛NullPointerException异常
try {
String s3 = null;
Optional<String> stringOptional3 = Optional.ofNullable(s3).map(null);
System.out.println(stringOptional3.orElse("default"));
} catch (Exception e) {
}
(8)<U> Optional<U> flatMap (Function<? super T, Optional<U>> mapper) :flatMap与map方法类似,区别在于flatMap中的mapper返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。
//flatMap,输出 JACK
Optional<String> stringOptional4 = Optional.of("jack").flatMap((value) -> Optional.ofNullable(value.toUpperCase()));
System.out.println(stringOptional4.orElse("default"));
//flatMap,输出 default
Optional<String> stringOptional5 = Optional.of("jack").flatMap((value) -> Optional.ofNullable(null));
System.out.println(stringOptional5.orElse("default"));
//flatMap,输出 default,并且不会调用mapper
String s6 = null;
Optional<String> stringOptional6 = Optional.ofNullable(s6).flatMap((value) -> Optional.ofNullable(value.toUpperCase()));
System.out.println(stringOptional6.orElse("default"));
//flatMap 如果map的参数mapper为null,抛NullPointerException异常
try {
String s7 = null;
Optional<String> stringOptional7 = Optional.ofNullable(s7).flatMap(null);
System.out.println(stringOptional7.orElse("default"));
} catch (Exception e) {
System.out.println("出错了");
}
(9)Optional<T> filter (Predicate<? super T> predicate) :如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
//输出default
String filterString = Optional.of("hugo")
.filter(s -> "jack".equals(s))
.orElse("default");
System.out.println(filterString);
//输出hugo
String filterString2 = Optional.of("hugo")
.filter(s -> "hugo".equals(s))
.orElse("default");
System.out.println(filterString2);
//输出default,断言接口里面的语句不会执行
String nullableString = null;
String filterString3 = Optional.ofNullable(nullableString)
.filter(s -> {
System.out.println("测试是否调用");
return "jack".equals(s);
})
.orElse("default");
System.out.println(filterString3);
解决问题
经过上面学习Optional的相关API,已经对它有了一定的了解。下面,我们运用上面的知识解决在前言中遗留的问题。
ioscode = Optional.ofNullable(user)
.map(u -> u.getAddress())
.map(addr -> addr.getCountry())
.map(country -> country.getIosCode())
.map(String::toUpperCase)
.orElse("default");
从上面的学习可以知道,只有Optional是empty的,map方法不会被调用。
相关资料
Java 8 函数式编程系列
来源:oschina
链接:https://my.oschina.net/u/1400519/blog/2992379