public class Test { public static void main(String[] args) { People people = new People(); Optional<People> p = Optional.ofNullable(people); String name = p.flatMap(People::getCar).flatMap(Car::getInsurence).map(Insurence::getName).orElse("string"); } } class People{ private Optional<Car> car; public Optional<Car> getCar() { return car; } } class Car{ private Optional<Insurence> insurence; public Optional<Insurence> getInsurence() { return insurence; } } class Insurence{ String name; public String getName() { return name; } }
这篇写的很好,另外参考Java8实战html
http://blog.csdn.net/sun_promise/article/details/51362838java
Java8实战的一个例子程序员
到目前为止,著名的NullPointerException是致使Java应用程序失败的最多见缘由。过去,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava经过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。现在,受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。api
Optional:按照字面英文解释为“可选的” 意思,但此处的语义是指某个值可能有也可能没有(null)。promiseOptional 被定义为一个简单的容器,其值多是null或者不是null。在Java 8以前通常某个函数应该返回非空对象可是偶尔却可能返回了null,而在Java 8 之后,不推荐你返回null而是返回Optional。安全
Optional英文文档地址:http://docs.oracle.com/javase/8/docs/api/java/util/Optional.htmloracle
Java 8借鉴了Scala和Haskell,提供了一个新的Optional模板,能够用它来封装可能为空的引用。但它毫不是终结空指针,更多只是使API的设计者能够在代码层面声明一个方法可能会返回空值,调用方应该注意这种状况。所以,这只对新的API有效,前提是调用者不要让引用逃逸出封装类,不然引用可能会在外面被不安全的废弃掉。app
我的对这个新的特性是又爱又恨。一方面,空指针是一个大问题,只要能解决这个问题的东西笔者都欢迎。但另外一方面,我的对它是否能担此重任执怀疑的态度。这是因为使用它须要全公司的集体努力,短时间内很难会有见效。若非大力地推广使用,极可能会功亏一篑。less
1)显式的提醒你须要关注null的状况,对程序员是一种字面上的约束
2)将平时的一些显式的防护性检测给标准化了,并提供一些可串联操做
3)解决null会致使疑惑的概念eclipse
eg:Map里面的key==null的状况,以及value==null的状况
4.1 Optional类的官方描述
A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
(这是一个能够为null的容器对象。若是值存在则isPresent()方法会返回true,调用get()方法会返回该对象。)
4.2 Optional的简单使用
Optional类的包名:java.util.Optional<T>
为了防止抛出java.lang.NullPointerException 异常,咱们常常会写出这样的代码:
- Student student = person.find("Lucy");
- if (student != null) {
- student.doSomething();
- }
使用Optional的代码写法:
说明:若是isPresent()返回false,说明这是个空对象;不然,咱们就能够把其中的内容取出来作相应的操做了。
- Student student = person.find("Lucy");
- if (student.isPresent()) {
- student.get().doSomething();
- }
单从代码量上来讲,Optional的代码量并未减小,甚至比原来的代码还多。但好在,你绝对不会忘记判空,由于这里咱们获得的不是Student类的对象,而是Optional。
4.3Optional类的主要方法
1) of(T value)
为非null的值建立一个Optional。
of()方法经过工厂方法建立Optional类。须要注意,建立对象时传入的参数不能为null。若是传入参数为null,则抛出NullPointerException 。
eg:
- //调用工厂方法建立Optional实例
- Optional<String> myValue = Optional.of("OptionalTest");
- //传入参数为null,抛出NullPointerException.
- Optional<String> someNull = Optional.of(null);
2) ofNullable(T value)
为指定的值建立一个Optional,若是指定的值为null,则返回一个空的Optional。ofNullable与of方法类似,惟一的区别是能够接受参数为null的状况。
eg:
- //下面建立了一个不包含任何值的Optional实例
- //eg:值为'null'
- Optional empty = Optional.ofNullable(null);
3) isPresent()
若是值存在返回true,不然返回false。
eg:
- //isPresent()方法用来检查Optional实例中是否包含值
- if (myValue.isPresent()) {
- //在Optional实例内调用get()返回已存在的值
- System.out.println(myValue.get());//输出OptionalTest }
4) get()
若是Optional有值则将其返回,不然抛出异常 NoSuchElementException。
在上面的示例中,get方法用来获得Optional实例中的值。下面是一个抛出NoSuchElementException的示例:
eg:
- //执行下面的代码会输出:No value present
- try {
- //在空的Optional实例上调用get(),抛出NoSuchElementException
- System.out.println(empty.get());
- } catch (NoSuchElementException ex) {
- System.out.println(ex.getMessage());
- }
5) ifPresent(Consumer<? super T> consumer)
若是Optional实例有值则为其调用consumer,不然不作处理。
要理解ifPresent()方法,首先须要了解Consumer类。简单地说,Consumer类包含一个抽象方法。该抽象方法对传入的值进行处理,但没有返回值。Java8支持不用接口直接经过lambda表达式传入参数。
若是Optional实例有值,调用ifPresent()能够接受接口段或lambda表达式。
eg:
- //ifPresent()方法接受lambda表达式做为参数。
- //lambda表达式对Optional的值调用consumer进行处理。
- myValue.ifPresent((value) -> {
- System.out.println("The length of the value is: " + value.length());
- });
6) orElse(T other)
若是有值则将其返回,不然返回指定的其它值。
若是Optional实例有值则将其返回,不然返回orElse方法传入的参数。即:参数other为默认返回值eg:
- //若是值不为null,orElse方法返回Optional实例的值。
- //若是为null,返回传入的消息。
- //输出:There is no value present!
- System.out.println(empty.orElse("There is no value present!"));
- //输出:OptionalTest
- System.out.println(myValue.orElse("There is some value!"));
7) orElseGet(Supplier<? extends T> other)
orElseGet与orElse方法相似,区别在于获得的默认值。orElse方法将传入的参数字符串做为默认值,orElseGet方法能够接受Supplier接口的实现用来生成默认值。
eg:
- //orElseGet能够接受一个lambda表达式生成默认值。
- //输出:Default Value
- System.out.println(empty.orElseGet(() -> "Default Value"));
- //输出:OptionalTest
- System.out.println(myValue.orElseGet(() -> "Default Value"));
8) orElseThrow(Supplier<? extends X> exceptionSupplier)
若是有值则将其返回,不然抛出supplier接口建立的异常。
在orElseGet()方法中,咱们传入一个Supplier接口。然而,在orElseThrow中咱们能够传入一个lambda表达式或方法,若是值不存在就抛出异常。eg:
- try {
- //orElseThrow与orElse方法相似。与返回默认值不一样,
- //orElseThrow会抛出lambda表达式或方法生成的异常
- empty.orElseThrow(ValueAbsentException::new);
- } catch (Throwable ex) {
- //输出: No value present in the Optional instance
- System.out.println(ex.getMessage());
- }
- class ValueAbsentException extends Throwable {
- public ValueAbsentException() {
- super();
- }
- public ValueAbsentException(String msg) {
- super(msg);
- }
- @Override
- public String getMessage() {
- return "No value present in the Optional instance";
- }
- }
9) map(Function<? super T,? extends U> mapper)
若是有值,则对其执行调用mapping函数获得返回值。若是返回值不为null,则建立包含mapping返回值的Optional做为map方法返回值,不然返回空Optional。
map方法用来对Optional实例的值执行一系列操做。经过一组实现了Function接口的lambda表达式传入操做。eg:
- //map方法执行传入的lambda表达式参数对Optional实例的值进行修改。
- //为Lambda表达式的返回值建立新的Optional实例做为map方法的返回值。
- Optional<String> upperName = myValue.map((value) -> value.toUpperCase());
- System.out.println(upperName.orElse("No value found"));
10) flatMap(Function<? super T,Optional<U>> mapper)
若是有值,为其执行mapping函数返回Optional类型返回值,不然返回空Optional。flatMap与map(Funtion)方法相似,区别在于flatMap中的mapper返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。
flatMap方法与map方法相似,区别在于mapping函数的返回值不一样。map方法的mapping函数返回值能够是任何类型T,而flatMap方法的mapping函数必须是Optional。eg:
下面参照map函数,使用flatMap重写的示例
- //map方法中的lambda表达式返回值能够是任意类型,在map函数返回以前会包装为Optional。
- //但flatMap方法中的lambda表达式返回值必须是Optionl实例。
- upperName = myValue.flatMap((value) -> Optional.of(value.toUpperCase()));
- System.out.println(upperName.orElse("No value found"));
11) filter(Predicate<? super T> predicate)
若是有值而且知足断言条件返回包含该值的Optional,不然返回空Optional。
filter个方法经过传入限定条件对Optional实例的值进行过滤。对于filter函数咱们能够传入实现了Predicate接口的lambda表达式。
eg:
- //filter方法检查给定的Option值是否知足某些条件。
- //若是知足则返回同一个Option实例,不然返回空Optional。
- Optional<String> longName = myValue.filter((value) -> value.length() > 6);
- System.out.println(longName.orElse("The name is less than 6 characters"));//输出OptionalTest
- //另外一个例子是Optional值不知足filter指定的条件。
- Optional<String> anotherName = Optional.of("Test");
- Optional<String> shortName = anotherName.filter((value) -> value.length() > 6);
- //输出:name长度不足6字符
- System.out.println(shortName.orElse("The name is less than 6 characters"));
12) empty()
返回一个空Optional实例。
eg:
- Optional.<String>empty(); // 返回一个空Optional<String>
Note:
Optional有这么多方法,那Optional的初衷是什么?并且Optional也是一个对象,因此它自己也有多是null,这可如何是好。因此,我的认为,Optional比较适用的地方是做为返回值,这样能够给使用者一个善意的提醒。
4.4 map 与 flatMap 的区别
map(mapper) 与 flatMap(mapper) 功能上基本是同样的,只是最后的返回值不同。map(mapper)方法中的mapper能够返回任意类型,可是flatMap(mapper)方法中的mapper只能返回Optional类型。
若是mapper返回结果result的不是null,那么map就会返回一个Optional,可是 flatMap不会对result进行任何包装。
eg:
- Optional<String> o;
- o.map((value)->Optional.of(value)) //返回的类型是Optional<Optional<String>>
- o.flatMap((value)->Optional.of(value)) //返回的类型是Optional<String>
4.5 Optional应用示例:
Note:测试的时候最好是新建一个java项目(或者直接用eclipse测试),由于Android项目目前不彻底支持java8的新特性,须要配置不少东西,也同样容易出现各类问题。
- import java.util.NoSuchElementException;
- import java.util.Optional;
- public class OptionalTest {
- public static void main(String[] args) {
- // 建立Optional
- String mayBeNull = null;
- Optional<String> opt1 = Optional.of(" Hello! ");
- Optional<String> opt2 = Optional.ofNullable(mayBeNull);
- Optional<String> opt3 = Optional.empty();
- opt1.ifPresent(System.out::println); // " Hello! "
- opt2.ifPresent(System.out::println);
- opt3.ifPresent(System.out::println);
- //方法测试示例
- ofTest();
- ofNullableTest();
- isPresentTest();
- ifPresentTest();
- orElseTest();
- orElseGetTest();
- mapTest();
- flatMapTest();
- filterTest();
- }
- /**
- * of后面接给optional设置的值 可是不能为空 若是为空会报空指针异常
- */
- public static void ofTest() {
- Optional<String> optional = Optional.of("123");
- System.out.println(optional.get());
- try {
- optional = Optional.of(null);
- System.out.println("null值--"+optional.get()); //get方法是获取optional的值 类型取决于声明的时候
- } catch (NullPointerException e) {
- System.out.println("空指针异常");
- }
- }
- /**
- * ofNullable 和of相似 可是ofNullable能够设置null值 若是是Null值得话取值会报NoSuchElementException 异常
- */
- public static void ofNullableTest() {
- Optional<String> optional = Optional.ofNullable("123");
- System.out.println(optional.get());
- try {
- optional = Optional.ofNullable(null);
- System.out.println("null值---"+optional.get());
- } catch (NoSuchElementException e) {
- System.out.println("NoSuchElementException 异常");
- }
- }
- /**
- * ifPresent用来判断optional中有没有值存在 若是有则为真
- */
- public static void isPresentTest() {
- Optional<String> optional = Optional.ofNullable(null);
- if (optional.isPresent()) {
- System.out.println(optional.get());
- } else {
- System.out.println("值为空");
- }
- }
- /**
- * ifPresent和isPresent相似 只不过它支持λ表达式
- */
- public static void ifPresentTest() {
- Optional<String> optional = Optional.ofNullable("123");
- optional.ifPresent(var -> {
- System.out.println(var);
- });
- }
- /**
- * orElse方法,若是值为空的话会用参数中的值去替换 即设置默认值
- */
- public static void orElseTest() {
- Optional<String> optional = Optional.ofNullable("123");
- System.out.println(optional.orElse("有没有"));
- optional = Optional.ofNullable(null);
- System.out.println(optional.orElse("有没有000"));
- }
- /**
- * orElseGet方法 和orElse相似 不过此方法接受Supplier接口的实现用来生成默认值
- */
- public static void orElseGetTest() {
- Optional<String> optional = Optional.ofNullable("123");
- System.out.println(optional.orElseGet(() -> "123456"));
- optional = Optional.ofNullable(null);
- System.out.println(optional.orElseGet(() -> "1234567"));
- }
- /**
- * map方法 若是有值则会对值进行mapping中的处理 处理结果存在则建立并返回Optional类型的结果 不然返回空
- */
- public static void mapTest() {
- Optional<String> optional = Optional.ofNullable("abc");
- System.out.println(optional.map(var -> var.toUpperCase()).get());
- }
- /**
- * flatMap和map相似 只不过mapping中必须返回Option类型的数据
- */
- public static void flatMapTest() {
- Optional<String> optional = Optional.ofNullable("abc");
- System.out.println(optional.flatMap(var -> Optional.of(var.toUpperCase())).get());
- }
- /**
- * filter对optional进行过滤,mapping中为过滤的条件 若是不知足条件 返回一个为空的Optional
- */
- public static void filterTest() {
- try {
- Optional<String> optional = Optional.ofNullable("一二三四五六七八");
- System.out.println(optional.filter(var -> var.length() > 6).get());
- System.out.println(optional.filter(var -> var.length() < 6).get());
- } catch (NoSuchElementException e) {
- System.out.println("optional的值为空");
- }
- }
- }