一、基本介绍

  1. 身为一名Java程序员,大家可能都有这样的经历: 调用一个方法得到了返回值却不能直接将返回值作为参数去调用别的方法。我们首先要判断这个返回值是否为null,只有在非空的前提下才能将其作为其他方法的参数。这正是一些类似Guava的外部API试图解决的问题。一些JVM编程语言比如Scala、Ceylon等已经将对在核心API中解决了这个问题。
  2. 新版本的Java,比如Java 8引入了一个新的Optional类。Optional类的Javadoc描述如下:

    1. 这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

      二、常用API

      1. public class OptionalApiTest {
      2. /**
      3. * of
      4. * 为非null的值创建一个Optional。
      5. * of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。
      6. */
      7. @Test
      8. public void ofTest() {
      9. //调用工厂方法创建Optional实例
      10. Optional<String> name = Optional.of("Sanaulla");
      11. System.out.println(name); // Optional[Sanaulla]
      12. System.out.println(name.get()); // Sanaulla
      13. //传入参数为null,抛出NullPointerException.
      14. Optional<String> someNull = Optional.of(null);
      15. }
      16. /**
      17. * ofNullable
      18. * 为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。
      19. * ofNullable与of方法相似,唯一的区别是可以接受参数为null的情况。示例如下:
      20. */
      21. @Test
      22. public void ofNullableTest() {
      23. //下面创建了一个不包含任何值的Optional实例
      24. //例如,值为'null'
      25. Optional empty = Optional.ofNullable(null);
      26. System.out.println(empty); // Optional.empty
      27. }
      28. /**
      29. * isPresent
      30. * 如果值存在返回true,否则返回false。
      31. * get() : 如果Optional有值则将其返回,否则抛出NoSuchElementException。
      32. */
      33. @Test
      34. public void isPresentTest() {
      35. // isPresent方法用来检查Optional实例中是否包含值
      36. // Optional<String> name = Optional.ofNullable(null); // 不包含
      37. Optional<String> name = Optional.of("Sanaulla"); // 包含
      38. if (name.isPresent()) {
      39. //在Optional实例内调用get()返回已存在的值
      40. System.out.println(name.get());//输出Sanaulla
      41. }
      42. }
      43. /**
      44. * isPresent
      45. * 如果Optional实例有值则为其调用consumer,否则不做处理
      46. * 如果Optional实例有值,调用ifPresent()可以接受接口段或lambda表达式
      47. */
      48. @Test
      49. public void isPresentTest01() {
      50. Optional<String> name = Optional.of("Sanaulla");
      51. // ifPresent方法接受lambda表达式作为参数。
      52. // lambda表达式对Optional的值调用consumer进行处理。
      53. // 即Optional的值作为参数传递进lamdba表达式的参数中
      54. name.ifPresent((value) -> {
      55. System.out.println("The length of the value is: " + value.length());
      56. });
      57. }
      58. /**
      59. * orElse
      60. * 如果有值则将其返回,否则返回指定的其它值。
      61. */
      62. @Test
      63. public void orElseTest() {
      64. Optional empty = Optional.ofNullable(null);
      65. Optional<String> name = Optional.of("Sanaulla");
      66. //如果值不为null,orElse方法返回Optional实例的值。
      67. //如果为null,返回传入的消息。
      68. //输出: There is no value present!
      69. System.out.println(empty.orElse("There is no value present!"));
      70. //输出: Sanaulla
      71. System.out.println(name.orElse("There is some value!"));
      72. }
      73. /**
      74. * orElseGet
      75. * orElseGet与orElse方法类似,区别在于得到的默认值。
      76. * orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。示例如下:
      77. */
      78. @Test
      79. public void orElseGetTest() {
      80. Optional empty = Optional.ofNullable(null);
      81. Optional<String> name = Optional.of("Sanaulla");
      82. //orElseGet与orElse方法类似,区别在于orElse传入的是默认值,
      83. //orElseGet可以接受一个lambda表达式生成默认值。
      84. //输出: Default Value
      85. System.out.println(empty.orElseGet(() -> "Default Value"));
      86. //输出: Sanaulla
      87. System.out.println(name.orElseGet(() -> "Default Value"));
      88. }
      89. /**
      90. * orElseThrow
      91. * 如果有值则将其返回,否则抛出supplier接口创建的异常。
      92. * 在orElseGet方法中,我们传入一个Supplier接口。
      93. * 然而,在orElseThrow中我们可以传入一个lambda表达式或方法,如果值不存在来抛出异常。
      94. */
      95. @Test
      96. public void orElseThrowTest() {
      97. Optional empty = Optional.ofNullable(null);
      98. try {
      99. //orElseThrow与orElse方法类似。与返回默认值不同,
      100. //orElseThrow会抛出lambda表达式或方法生成的异常
      101. empty.orElseThrow(NullPointerException::new);
      102. } catch (Throwable ex) {
      103. System.out.println(ex.getMessage());
      104. }
      105. }
      106. /**
      107. * map
      108. * 如果有值,则对其执行调用mapping函数得到返回值。
      109. * 如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
      110. * map方法用来对Optional实例的值执行一系列操作。通过一组实现了Function接口的lambda表达式传入操作。
      111. */
      112. @Test
      113. public void mapTest() {
      114. Optional<String> name = Optional.of("Sanaulla");
      115. // map方法执行传入的lambda表达式参数对Optional实例的值进行修改。
      116. // 为lambda表达式的返回值创建新的Optional实例作为map方法的返回值。
      117. Optional<String> upperName = name.map((value) -> value.toUpperCase());
      118. System.out.println(upperName.orElse("No value found"));
      119. }
      120. /**
      121. * flatMap
      122. * 如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。
      123. * flatMap与map(Funtion)方法类似,区别在于flatMap中的mapper返回值必须是Optional。调
      124. * 用结束时,flatMap不会对结果用Optional封装。
      125. *
      126. * flatMap方法与map方法类似,区别在于mapping函数的返回值不同。map方法的mapping函数返回值可以是任何类型T,
      127. * 而flatMap方法的mapping函数必须是Optional。
      128. */
      129. @Test
      130. public void flatMapTest() {
      131. Optional<String> name = Optional.of("Sanaulla");
      132. // flatMap与map(Function)非常类似,区别在于传入方法的lambda表达式的返回类型。
      133. // map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。
      134. // 但flatMap方法中的lambda表达式返回值必须是Optionl实例。
      135. Optional<String> upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));
      136. System.out.println(upperName.orElse("No value found"));//输出SANAULLA
      137. }
      138. /**
      139. * filter
      140. * filter个方法通过传入限定条件对Optional实例的值进行过滤。文档描述如下:
      141. * 如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
      142. */
      143. @Test
      144. public void filterTest() {
      145. Optional<String> name = Optional.of("Sanaulla");
      146. // filter方法检查给定的Option值是否满足某些条件。
      147. // 如果满足则返回同一个Option实例,否则返回空Optional。
      148. Optional<String> longName = name.filter((value) -> value.length() > 6);
      149. System.out.println(longName.orElse("The name is less than 6 characters"));// 输出Sanaulla
      150. // 另一个例子是Optional值不满足filter指定的条件。
      151. Optional<String> anotherName = Optional.of("Sana");
      152. Optional<String> shortName = anotherName.filter((value) -> value.length() > 6);
      153. // 输出: name长度不足6字符
      154. System.out.println(shortName.orElse("The name is less than 6 characters"));
      155. }
      156. }