为您推荐:
精华内容
最热下载
问答
  • public class Test { public static void main(String[] args) { People people = new People();... Optional<People> p = Optional.ofNullable(people); String name = p.flatMap(People::getCa...
    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;
      }
    }

     

    1.Optional简述 

    到目前为止,著名的NullPointerException是导致Java应用程序失败的最常见原因。过去,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。如今,受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。


    Optional:按照字面英文解释为“可选的” 意思,但此处的语义是指某个值可能有也可能没有(null)

    Optional 被定义为一个简单的容器,其值可能是null或者不是null。在Java 8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java 8 以后,不推荐你返回null而是返回Optional。

     

    Optional英文文档地址:http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html

     

    2.对 Optional 应用的理解

    Java 8借鉴了Scala和Haskell,提供了一个新的Optional模板,可以用它来封装可能为空的引用。但它绝不是终结空指针,更多只是使API的设计者可以在代码层面声明一个方法可能会返回空值,调用方应该注意这种情况。因此,这只对新的API有效,前提是调用者不要让引用逃逸出封装类,否则引用可能会在外面被不安全的废弃掉。

    个人对这个新的特性是又爱又恨。一方面,空指针是一个大问题,只要能解决这个问题的东西笔者都欢迎。但另一方面,个人对它是否能担此重任执怀疑的态度。这是由于使用它需要全公司的集体努力,短期内很难会有见效。若非大力地推广使用,很可能会功亏一篑。

     

    3.Optional的优点

    1)显式的提醒你需要关注null的情况,对程序员是一种字面上的约束
    2)将平时的一些显式的防御性检测给标准化了,并提供一些可串联操作

    3)解决null会导致疑惑的概念

    eg:Map里面的key==null的情况,以及value==null的情况

     

    4.Optional类

     

    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 异常,我们经常会写出这样的代码:

     

    [java]  view plain  copy

     

    1. Student student = person.find("Lucy");  
    2.         if (student != null) {  
    3.             student.doSomething();  
    4.         }  

    使用Optional的代码写法:

     

     

    [java]  view plain  copy

     

    1. Student student = person.find("Lucy");  
    2.         if (student.isPresent()) {  
    3.             student.get().doSomething();  
    4.         }  
    说明:如果isPresent()返回false,说明这是个空对象;否则,我们就可以把其中的内容取出来做相应的操作了。
    单从代码量上来说,Optional的代码量并未减少,甚至比原来的代码还多。但好在,你绝对不会忘记判空,因为这里我们得到的不是Student类的对象,而是Optional。

     

     

    4.3Optional类的主要方法

    1) of(T value)

    为非null的值创建一个Optional。

    of()方法通过工厂方法创建Optional类。需要注意,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。

    eg:

     

    [java]  view plain  copy

     

    1. //调用工厂方法创建Optional实例  
    2.     Optional<String> myValue = Optional.of("OptionalTest");  
    3.     //传入参数为null,抛出NullPointerException.  
    4.     Optional<String> someNull = Optional.of(null);  

     

     

    2) ofNullable(T value)

    为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。

    ofNullable与of方法相似,唯一的区别是可以接受参数为null的情况。

    eg:

     

    [java]  view plain  copy

     

    1. //下面创建了一个不包含任何值的Optional实例  
    2. //eg:值为'null'  
    3. Optional empty = Optional.ofNullable(null);  

     

     

    3) isPresent()

    如果值存在返回true,否则返回false。

    eg:

     

    [java]  view plain  copy

     

    1. //isPresent()方法用来检查Optional实例中是否包含值  
    2. if (myValue.isPresent()) {  
    3. //在Optional实例内调用get()返回已存在的值  
    4. System.out.println(myValue.get());//输出OptionalTest }  
     

     

    4) get()

    如果Optional有值则将其返回,否则抛出异常 NoSuchElementException。

    在上面的示例中,get方法用来得到Optional实例中的值。下面是一个抛出NoSuchElementException的示例:

    eg:

     

    [java]  view plain  copy

     

    1. //执行下面的代码会输出:No value present   
    2.         try {  
    3.           //在空的Optional实例上调用get(),抛出NoSuchElementException  
    4.           System.out.println(empty.get());  
    5.         } catch (NoSuchElementException ex) {  
    6.           System.out.println(ex.getMessage());  
    7.         }  
     

     

    5) ifPresent(Consumer<? super T> consumer)

    如果Optional实例有值则为其调用consumer,否则不做处理。

    要理解ifPresent()方法,首先需要了解Consumer类。简单地说,Consumer类包含一个抽象方法。该抽象方法对传入的值进行处理,但没有返回值。Java8支持不用接口直接通过lambda表达式传入参数。

    如果Optional实例有值,调用ifPresent()可以接受接口段或lambda表达式。

    eg:

     

    [java]  view plain  copy

     

    1. //ifPresent()方法接受lambda表达式作为参数。  
    2.         //lambda表达式对Optional的值调用consumer进行处理。  
    3.         myValue.ifPresent((value) -> {  
    4.           System.out.println("The length of the value is: " + value.length());  
    5.         });  

     

     

    6) orElse(T other)

    如果有值则将其返回,否则返回指定的其它值。
    如果Optional实例有值则将其返回,否则返回orElse方法传入的参数。即:参数other为默认返回值

    eg:

     

    [java]  view plain  copy

     

    1. //如果值不为null,orElse方法返回Optional实例的值。  
    2.         //如果为null,返回传入的消息。  
    3.         //输出:There is no value present!  
    4.         System.out.println(empty.orElse("There is no value present!"));  
    5.         //输出:OptionalTest  
    6.         System.out.println(myValue.orElse("There is some value!"));  

     

     

    7) orElseGet(Supplier<? extends T> other)

    orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的参数字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。

    eg:

     

    [java]  view plain  copy

     

    1. //orElseGet可以接受一个lambda表达式生成默认值。  
    2.         //输出:Default Value  
    3.         System.out.println(empty.orElseGet(() -> "Default Value"));  
    4.         //输出:OptionalTest  
    5.         System.out.println(myValue.orElseGet(() -> "Default Value"));  

     

     

    8) orElseThrow(Supplier<? extends X> exceptionSupplier)

    如果有值则将其返回,否则抛出supplier接口创建的异常。
    在orElseGet()方法中,我们传入一个Supplier接口。然而,在orElseThrow中我们可以传入一个lambda表达式或方法,如果值不存在就抛出异常。

    eg:

     

    [java]  view plain  copy

     

    1. try {  
    2.           //orElseThrow与orElse方法类似。与返回默认值不同,  
    3.           //orElseThrow会抛出lambda表达式或方法生成的异常   
    4.            
    5.           empty.orElseThrow(ValueAbsentException::new);  
    6.         } catch (Throwable ex) {  
    7.           //输出: No value present in the Optional instance  
    8.           System.out.println(ex.getMessage());  
    9.         }  

     

    [java]  view plain  copy

     

    1. class ValueAbsentException extends Throwable {  
    2.    
    3.   public ValueAbsentException() {  
    4.     super();  
    5.   }  
    6.    
    7.   public ValueAbsentException(String msg) {  
    8.     super(msg);  
    9.   }  
    10.    
    11.   @Override  
    12.   public String getMessage() {  
    13.     return "No value present in the Optional instance";  
    14.   }  
    15. }  
     

     

     

    9) map(Function<? super T,? extends U> mapper)

    如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
    map方法用来对Optional实例的值执行一系列操作。通过一组实现了Function接口的lambda表达式传入操作。

    eg:

     

    [java]  view plain  copy

     

    1. //map方法执行传入的lambda表达式参数对Optional实例的值进行修改。  
    2. //为Lambda表达式的返回值创建新的Optional实例作为map方法的返回值。  
    3. Optional<String> upperName = myValue.map((value) -> value.toUpperCase());  
    4. 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重写的示例

     

    [java]  view plain  copy

     

    1. //map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。   
    2. //但flatMap方法中的lambda表达式返回值必须是Optionl实例。   
    3. upperName = myValue.flatMap((value) -> Optional.of(value.toUpperCase()));  
    4. System.out.println(upperName.orElse("No value found"));  
     

     

    11) filter(Predicate<? super T> predicate)

    如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。


    filter个方法通过传入限定条件对Optional实例的值进行过滤。

    对于filter函数我们可以传入实现了Predicate接口的lambda表达式。

    eg:

     

    [java]  view plain  copy

     

    1. //filter方法检查给定的Option值是否满足某些条件。  
    2.     //如果满足则返回同一个Option实例,否则返回空Optional。  
    3.     Optional<String> longName = myValue.filter((value) -> value.length() > 6);  
    4.     System.out.println(longName.orElse("The name is less than 6 characters"));//输出OptionalTest  
    5.        
    6.     //另一个例子是Optional值不满足filter指定的条件。  
    7.     Optional<String> anotherName = Optional.of("Test");  
    8.     Optional<String> shortName = anotherName.filter((value) -> value.length() > 6);  
    9.     //输出:name长度不足6字符  
    10.     System.out.println(shortName.orElse("The name is less than 6 characters"));  
     

     

    12) empty()

    返回一个空Optional实例。

    eg:

     

    [java]  view plain  copy

     

    1. 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:

     

    [java]  view plain  copy

     

    1. Optional<String> o;  
    2. o.map((value)->Optional.of(value)) //返回的类型是Optional<Optional<String>>  
    3. o.flatMap((value)->Optional.of(value)) //返回的类型是Optional<String>  
     

     

    4.5 Optional应用示例:

    Note:测试的时候最好是新建一个java项目(或者直接用eclipse测试),因为Android项目目前不完全支持java8的新特性,需要配置很多东西,也一样容易出现各种问题。

     

    [java]  view plain  copy

     

    1. import java.util.NoSuchElementException;  
    2. import java.util.Optional;  
    3.   
    4. public class OptionalTest {  
    5.   
    6.     public static void main(String[] args) {  
    7.          // 创建Optional  
    8.         String mayBeNull = null;  
    9.         Optional<String> opt1 = Optional.of(" Hello! ");  
    10.         Optional<String> opt2 = Optional.ofNullable(mayBeNull);  
    11.         Optional<String> opt3 = Optional.empty();  
    12.         opt1.ifPresent(System.out::println); // " Hello! "  
    13.         opt2.ifPresent(System.out::println);  
    14.         opt3.ifPresent(System.out::println);  
    15.   
    16.         //方法测试示例  
    17.         ofTest();  
    18.         ofNullableTest();  
    19.         isPresentTest();  
    20.         ifPresentTest();  
    21.         orElseTest();  
    22.         orElseGetTest();  
    23.         mapTest();  
    24.         flatMapTest();  
    25.         filterTest();  
    26.   
    27.     }  
    28.       
    29.     /** 
    30.      * of后面接给optional设置的值 但是不能为空 如果为空会报空指针异常 
    31.      */  
    32.     public static void ofTest() {  
    33.         Optional<String> optional = Optional.of("123");  
    34.         System.out.println(optional.get());  
    35.         try {  
    36.             optional = Optional.of(null);  
    37.             System.out.println("null值--"+optional.get());  //get方法是获取optional的值 类型取决于声明的时候  
    38.         } catch (NullPointerException e) {  
    39.             System.out.println("空指针异常");  
    40.         }  
    41.     }  
    42.   
    43.     /** 
    44.      * ofNullable 和of类似 但是ofNullable可以设置null值  如果是Null值得话取值会报NoSuchElementException 异常 
    45.      */  
    46.     public static void ofNullableTest() {  
    47.         Optional<String> optional = Optional.ofNullable("123");  
    48.         System.out.println(optional.get());  
    49.         try {  
    50.             optional = Optional.ofNullable(null);  
    51.             System.out.println("null值---"+optional.get());  
    52.         } catch (NoSuchElementException e) {  
    53.             System.out.println("NoSuchElementException 异常");  
    54.         }  
    55.     }  
    56.   
    57.     /** 
    58.      * ifPresent用来判断optional中有没有值存在 如果有则为真 
    59.      */  
    60.     public static void isPresentTest() {  
    61.         Optional<String> optional = Optional.ofNullable(null);  
    62.         if (optional.isPresent()) {  
    63.             System.out.println(optional.get());  
    64.         } else {  
    65.             System.out.println("值为空");  
    66.         }  
    67.     }  
    68.   
    69.     /** 
    70.      * ifPresent和isPresent类似 只不过它支持λ表达式 
    71.      */  
    72.     public static void ifPresentTest() {  
    73.         Optional<String> optional = Optional.ofNullable("123");  
    74.         optional.ifPresent(var -> {  
    75.             System.out.println(var);  
    76.         });  
    77.     }  
    78.   
    79.     /** 
    80.      * orElse方法,如果值为空的话会用参数中的值去替换 即设置默认值 
    81.      */  
    82.     public static void orElseTest() {  
    83.         Optional<String> optional = Optional.ofNullable("123");  
    84.         System.out.println(optional.orElse("有没有"));  
    85.         optional = Optional.ofNullable(null);  
    86.         System.out.println(optional.orElse("有没有000"));  
    87.     }  
    88.   
    89.     /** 
    90.      * orElseGet方法 和orElse类似 不过此方法接受Supplier接口的实现用来生成默认值 
    91.      */  
    92.     public static void orElseGetTest() {  
    93.         Optional<String> optional = Optional.ofNullable("123");  
    94.         System.out.println(optional.orElseGet(() -> "123456"));  
    95.         optional = Optional.ofNullable(null);  
    96.         System.out.println(optional.orElseGet(() -> "1234567"));  
    97.     }  
    98.   
    99.     /** 
    100.      * map方法  如果有值则会对值进行mapping中的处理 处理结果存在则创建并返回Optional类型的结果 否则返回空 
    101.      */  
    102.     public static void mapTest() {  
    103.         Optional<String> optional = Optional.ofNullable("abc");  
    104.         System.out.println(optional.map(var -> var.toUpperCase()).get());  
    105.     }  
    106.   
    107.     /** 
    108.      * flatMap和map类似 只不过mapping中必须返回Option类型的数据 
    109.      */  
    110.     public static void flatMapTest() {  
    111.         Optional<String> optional = Optional.ofNullable("abc");  
    112.         System.out.println(optional.flatMap(var -> Optional.of(var.toUpperCase())).get());  
    113.     }  
    114.   
    115.     /** 
    116.      * filter对optional进行过滤,mapping中为过滤的条件  如果不满足条件 返回一个为空的Optional 
    117.      */  
    118.     public static void filterTest() {  
    119.         try {  
    120.             Optional<String> optional = Optional.ofNullable("一二三四五六七八");  
    121.             System.out.println(optional.filter(var -> var.length() > 6).get());  
    122.             System.out.println(optional.filter(var -> var.length() < 6).get());  
    123.         } catch (NoSuchElementException e) {  
    124.             System.out.println("optional的值为空");  
    125.         }  
    126.     }  
    127.   
    128. }  

     

    展开全文
    dylgs314118 2019-09-19 10:59:15
  • Optional类是java8引入的很有趣的一个类。Optional类主要解决的问题是臭名昭著的空指针异常问题(NullPointerException)。 所谓空指针异常,就是指针指向一个空对象,既然是一个空对象那你就不能操作他,不能使用...

             Optional类是java8引入的很有趣的一个类。Optional类主要解决的问题是臭名昭著的空指针异常问题(NullPointerException)。

              所谓空指针异常,就是指针指向一个空对象,既然是一个空对象那你就不能操作他,不能使用这个对象的方法,如果你非要使用,那么就会产生空指针异常;

              除此之外,以下几种情况也会导致空指针异常;

    1.  对象存在,如果你访问或者修改对象不存在的属性的时候也会产生异常;
    2.  字符串变量未初始化;
    3.  接口类型的对象没有用具体的类初始化;

              本质上,Optional是一个包含有可选值的包装类,这意味着Optional类既可以含有对象也可以为空。

    在java8之前,任何访问对象方法或者属性的调用都可能导致NullPointerException:

        public static String getGender(Student student)
        {
            if(null == student)
            {
                return "Unkown";
            }
            return student.getGender();
            
        }

        这是一个获取学生性别的方法,方法入参味一个Student对象,为了防止student对象为null,坐了防御性检查,如果值为null,返回“Unkown”这就很容易变得冗长,难以维护;为了简化这个过程,我们来看看用Optional类是怎么做的。

    public static String getGender(Student student)
        {
           return Optional.ofNullable(student).map(u -> u.getGender()).orElse("Unkown");
            
        }

    可以看到,Optional类结合lambda表达式的使用能够让开发出的代码更简洁和优雅;

    Optional对象的创建

    我们先看下Optional类的部分源码:

        private static final Optional<?> EMPTY = new Optional<>();
    
        private final T value;
    
        private Optional() {
            this.value = null;
        }
    
        public static<T> Optional<T> empty() {
            @SuppressWarnings("unchecked")
            Optional<T> t = (Optional<T>) EMPTY;
            return t;
        }
    
        private Optional(T value) {
            this.value = Objects.requireNonNull(value);
        }
    
        public static <T> Optional<T> of(T value) {
            return new Optional<>(value);
        }
    
        public static <T> Optional<T> ofNullable(T value) {
            return value == null ? empty() : of(value);
        }

    可以看出,Optional类的两个构造方法都是private型的,因此类外部不能显式的使用new Optional()的方式来创建Optional对象,但是Optional类提供了三个静态方法empty()、of(T value)、ofNullable(T value)来创建Optional对象,示例如下:

    // 1、创建一个包装对象值为空的Optional对象
    Optional<String> optStr = Optional.empty();
    // 2、创建包装对象值非空的Optional对象
    Optional<String> optStr1 = Optional.of("optional");
    // 3、创建包装对象值允许为空的Optional对象
    Optional<String> optStr2 = Optional.ofNullable(null);

    Optional类典型接口的使用

    • get()方法

             get()方法的源码如下:

        public T get() {
            if (value == null) {
                throw new NoSuchElementException("No value present");
            }
            return value;
        }

       可以看到,get()方法主要用于返回包装对象的实际值,但是如果包装对象值为null,会抛出NoSuchElementException异常。

    • isPresent()方法

             isPresent()方法的源码:

        public boolean isPresent() {
            return value != null;
        }

       可以看到,isPresent()方法用于判断包装对象的值是否非空。下面我们来看一段糟糕的代码:

    • ifPresent()方法

               ifPresent()方法的源码:

        public void ifPresent(Consumer<? super T> consumer) {
            if (value != null)
                consumer.accept(value);
        }

        ifPresent()方法接受一个Consumer对象(消费函数),如果包装对象的值非空,运行Consymer对象的accept()方法。示例如下:

        public static void printName(Student student)
        {
            Optional.ofNullable(student).ifPresent(u ->  System.out.println("The student name is : " + u.getName()));
        }
    • filter()方法

        filter()方法源码:

        public Optional<T> filter(Predicate<? super T> predicate) {
            Objects.requireNonNull(predicate);
            if (!isPresent())
                return this;
            else
                return predicate.test(value) ? this : empty();
        }

    filter()方法接受参数为Predicate对象,用于对Optional对象进行过滤,如果符合Predicate的条件,返回Optional对象本身,否则返回一个空的Optional对象。举例如下:

        public static void filterAge(Student student)
        {
            Optional.ofNullable(student).filter( u -> u.getAge() > 18).ifPresent(u ->  System.out.println("The student age is more than 18."));
        }
    • map()方法

         map方法的源码:

        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));
            }
        }

    map()方法的参数为Function(函数式接口)对象,map()方法将Optional中的包装对象用Function函数进行运算,并包装成新的Optional对象(包装对象的类型可能改变)。举例如下:

        public static Optional<Integer> getAge(Student student)
        {
            return Optional.ofNullable(student).map(u -> u.getAge()); 
        }

    上述代码中,先用ofNullable()方法构造一个Optional<Student>对象,然后用map()计算学生的年龄,返回Optional<Integer>对象(如果student为null, 返回map()方法返回一个空的Optinal对象)。

    • flatMap()方法

    flatMap()方法的源码:

        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));
            }
        }

    跟map()方法不同的是,入参Function函数的返回值类型为Optional<U>类型,而不是U类型,这样flatMap()能将一个二维的Optional对象映射成一个一维的对象。以3.5中示例功能为例,进行faltMap()改写如下:

        public static Optional<Integer> getAge(Student student)
        {
            return Optional.ofNullable(student).flatMap(u -> Optional.ofNullable(u.getAge())); 
        }
    • orElse()方法

    orElse()方法的源码:

        public T orElse(T other) {
            return value != null ? value : other;
        }

    orElse()方法功能比较简单,即如果包装对象值非空,返回包装对象值,否则返回入参other的值(默认值)。示例如下:

        public static String getGender(Student student)
        {
           return Optional.ofNullable(student).map(u -> u.getGender()).orElse("Unkown");
            
        }
    • orElseGet()方法

    orElseGet()方法的源码:

        public T orElseGet(Supplier<? extends T> other) {
            return value != null ? value : other.get();
        }

    orElseGet()方法与orElse()方法类似,区别在于orElseGet()方法的入参为一个Supplier对象,用Supplier对象的get()方法的返回值作为默认值。如:

        public static String getGender(Student student)
        {
            return Optional.ofNullable(student).map(u -> u.getGender()).orElseGet(() -> "Unkown");      
        }
    • orElseThrow()方法

    orElseThrow()方法的源码:

        public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
            if (value != null) {
                return value;
            } else {
                throw exceptionSupplier.get();
            }
        }

    orElseThrow()方法其实与orElseGet()方法非常相似了,入参都是Supplier对象,只不过orElseThrow()的Supplier对象必须返回一个Throwable异常,并在orElseThrow()中将异常抛出:

        public static String getGender1(Student student)
        {
            return Optional.ofNullable(student).map(u -> u.getGender()).orElseThrow(() -> new RuntimeException("Unkown"));      
        }

    orElseThrow()方法适用于包装对象值为空时需要抛出特定异常的场景。

    展开全文
    weixin_40159122 2020-02-19 13:54:36
  • Optional 是 Java 8 的新特性,专治空指针异常(NullPointerException, 简称 NPE)问题,它是一个容器类,里面只存储一个元素(这点不同于 Conllection)。 为方便用户通过 Lambda 表达式调用Optional 的方法,部分...

    1 前言

    Optional 是 Java 8 的新特性,专治空指针异常(NullPointerException, 简称 NPE)问题,它是一个容器类,里面只存储一个元素(这点不同于 Conllection)。

    为方便用户通过 Lambda 表达式调用 Optional 的方法,部分方法(如:filter、ifPresent、map、orElseGet)需传入函数式接口(如:Predicate、Consumer、Function、Supplier)参数。关于 Lambda 表达式的介绍,详见→Lambda 表达式总结

    2 主要属性及构造方法

    (1)类定义

    Optional 类位于 java.util 包中,类定义如下:

    //T 为元素数据类型
    public final class Optional<T>

    (2)主要属性

    //空容器
    private static final Optional<?> EMPTY = new Optional<>();
    
    //value 存储容器内唯一元素
    private final T value;

    (3)构造方法

    //无参构造方法:this.value = null
    private Optional()
    
    //有参构造方法(value不允许为空):this.value = Objects.requireNonNull(value)
    private Optional(T value)

    3 常用方法

    (1)创建容器(empty、of、ofNullable)

    //创建空容器:return (Optional<T>) EMPTY
    public static<T> Optional<T> empty()
    
    //创建容器(value不允许为空):return new Optional<>(value)
    public static <T> Optional<T> of(T value)
    
    //创建容器(value允许为空):return value == null ? empty() : of(value)
    public static <T> Optional<T> ofNullable(T value)

    (2)容器判空(isPresent)

    //判断容器是否为空:return value != null
    public boolean isPresent()
    
    //判断容器是否为空,若不为空,消费元素
    public void ifPresent(Consumer<? super T> consumer) {
    	if (value != null)
    		consumer.accept(value);
    }

    应用:

    Optional<User> op = Optional.of(new User("张三", 20));
    op.ifPresent(user -> System.out.println(user));
    //op.ifPresent(System.out::println);

    (3)获取元素(get、orElse、orElseGet)

    //获取容器中唯一元素:return value
    public T get()
    
    //获取容器唯一元素,若为空,返回指定值:return value != null ? value : other
    public T orElse(T other)
    
    //获取容器唯一元素,若为空,返回供应者(Supplier)提供的元素
    public T orElseGet(Supplier<? extends T> other) {
    	return value != null ? value : other.get();
    }

    应用: 

    Optional<User> op = Optional.ofNullable(null);
    User user = op.orElseGet(() -> new User("张三", 20));

    (4)筛选元素(filter)

    //过滤不符合断言(Predicate)的元素
    public Optional<T> filter(Predicate<? super T> predicate) {
    	Objects.requireNonNull(predicate);
    	if (!isPresent())
    		return this;
    	else
    		return predicate.test(value) ? this : empty();
    }

     应用: 

    Optional<User> op = Optional.of(new User("张三", 20));
    Optional<User> op2 = op.filter(user -> user.age > 18);

    (5)映射元素(map)

    //将 T 类型元素映射为 U 类型元素
    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<String> op = Optional.of(new String("12345"));
    Optional<Integer> op2 = op.map(str -> {
    	try {
    		return Integer.parseInt(str);
    	} catch (Exception e) {
    		return -1;
    	}
    });
    展开全文
    m0_37602827 2021-02-08 00:17:15
  • 目录1、初始化方法说明:ofNullable(T value)、of(T value)、empty()ofNullable(T value)of(T value)empty()2、功能方法说明isPresent()ifPresent()orElseorElseGetorElseThrow3、实际应用方法1方法2方法34、总结 ...

    1、初始化方法说明:ofNullable(T value)、of(T value)、empty()

    ofNullable(T value)

    • 允许传递一个为null的值,是null的话调用empty()方法,否则调用of(T value)方法
        public static <T> Optional<T> ofNullable(T value) {
            return value == null ? empty() : of(value);
        }
    

    of(T value)

    • 不允许传递null值,否则会抛出异常NullPointerException,将T值调用构造方法赋值给value
        public static <T> Optional<T> of(T value) {
            return new Optional<>(value);
        }
    
        private Optional(T value) {
            this.value = Objects.requireNonNull(value);
        }
        
        public static <T> T requireNonNull(T obj) {
            if (obj == null)
                throw new NullPointerException();
            return obj;
        }
    

    empty()

    • 生成一个value为null的对象
        public static<T> Optional<T> empty() {
            @SuppressWarnings("unchecked")
            Optional<T> t = (Optional<T>) EMPTY;
            return t;
        }
        
        private static final Optional<?> EMPTY = new Optional<>();
        
        // 无参构造直接设置value=null
        private Optional() {
            this.value = null;
        }
    

    2、功能方法说明

    isPresent()

    • // 判断是否为null,不为null返回true
        // 源码
        public boolean isPresent() {
            return value != null;
        }
    

    在这里插入图片描述

    ifPresent()

    • 值不为null,则进入ifPresent方法,执行输入的函数
        // 源码
        public void ifPresent(Consumer<? super T> consumer) {
            if (value != null)
                consumer.accept(value);
        }
    

    在这里插入图片描述

    orElse

    • 值为null,返回orElse的参数,否则返回原值
        // 源码
        public T orElse(T other) {
            return value != null ? value : other;
        }
    

    在这里插入图片描述

    orElseGet

    • 值为null,进入orElse中接收的函数,返回函数的返回值(和orElse比较:返回值一样,但是函数中可以做一些其他的操作)。
        public T orElseGet(Supplier<? extends T> other) {
            return value != null ? value : other.get();
        }
        // 函数式接口,无参,有返回值
        @FunctionalInterface
        public interface Supplier<T> {
    
    	   /**
    	    * Gets a result.
    	    *
    	    * @return a result
    	    */
    	   T get();
        }
    

    在这里插入图片描述

    orElseThrow

    • 值为null,进入orElse中接收的函数,抛出函数中自定义的异常。
        public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
            if (value != null) {
                return value;
            } else {
                throw exceptionSupplier.get();
            }
        }
    

    在这里插入图片描述

    3、实际应用

    • 举个例子,在用Stream流筛选list中的数据时,期望只得到一个结果,最终会有3种处理方式

    方法1

        public String get(){
            List<String> strings = Arrays.asList("a", "b", "c");
            List<String> d = strings.stream().filter(e -> e.equals("d")).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(d)){
                // 异常的处理逻辑,或return null,或抛出异常,或 return 自定义的值
                return "没找到,自定义一个值";
            }else {
                return d.get(0);
            }
        }
    

    方法2

        public String get(){
            List<String> strings = Arrays.asList("a", "b", "c");
            Optional<String> d = strings.stream().filter(e -> e.equals("d")).findFirst();
            if (d.isPresent()){
                return d.get();
            }else {
                // 异常的处理逻辑,或return null,或抛出异常,或 return 自定义的值
                return "没找到,自定义一个值";
            }
        }
    

    方法3

        public String get() {
            List<String> strings = Arrays.asList("a", "b", "c");
            return strings.stream().filter(e -> e.equals("d")).findFirst().orElse("没找到,自定义一个值");
        }
    

    4、总结

    从代码清晰度以及执行的流程,肯定第三种是最推荐的

    展开全文
    laolvbig 2021-09-26 17:32:45
  • fw118958 2017-12-22 11:51:02
  • weixin_45821811 2021-04-13 10:36:41
  • weixin_28358083 2021-02-12 11:41:37
  • lisemi 2019-08-07 15:21:57
  • weixin_34025386 2021-02-12 11:41:38
  • weixin_38370441 2021-01-07 15:37:36
  • sl1992 2019-08-21 23:54:25
  • qq_24532581 2020-01-07 15:26:28
  • qq_43842093 2021-10-09 21:50:52
  • sageyin 2021-08-05 12:24:41
  • weixin_36406678 2021-03-19 09:33:47
  • qq_31635851 2021-09-09 14:34:40
  • m0_45406092 2020-08-17 11:55:17
  • qq_31821675 2020-02-20 10:27:12
  • IT_private 2019-10-12 17:28:29
  • hwh295 2021-10-15 11:47:16
  • yangyangye 2019-02-18 15:46:15
  • qq_33591209 2021-10-18 16:08:41

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,123
精华内容 9,649
关键字:

optional详解