Optional:

1.问题引入

空指针问题是我们在开发中经常遇到的问题,例如:

class People{ 

      public String name ; 
      private int age;   
  
      public int getAge(){             
         return age;
      }

    public static void main(String args[])
    { 
       People people;    
       int age = people.getAge();
    }
    //会抛出空指针异常
}

传统的改正方法:

public static void main(String args[]){ 
      Peple people ;      
      if( people == null) 
        people = new People();   
      int age = people.getAge();
}

对于空指针问题,传统的方法是通过if 显式的判断对象是否为空或者使用try(){}catch{}语句,但是这样需要大量的显式操作,每遇到一个对象,都需要一个判断语句;因此,Java8引入Optional对象来避免空指针问题。

2.解决方法:Optional类

Optional类会对类进行简单的封装,变量不存在时,缺失的值会被建模成一个空的optional对象,由方法Optional.empty()返回,如果变量存在的话,返回包含的类型。

空的Optional对象和null之间的区别:

如果想解引用一个null,会触发空指针异常,使用Optioinal.empty()方法不会。

创建Optional对象:

Optional<People> optpeo = Optional.empty();
Optional<People> optpeo = Optional.of(people);
Optioinal<People> optpeo = Optional.ofNullable(people);// 允许null值的Optional对象;

Optional的Map方法和flatMap方法:

Optinal类提供一个map方法,用来提取和转换optional对象中的值,Optional<Integer> age = optpeo.map(people::getage);map方法会将函数应用到流中的每个元素;flatMap方法用来链接Optional对象:

Optional<people> optPeople = Optional.of(people);
Optional<Double> prices =
                 optPerson.map(people::getCar)                             
                          .map(Car::getType)
                          .map(Type::getPrice);
/**
* people::getCar 返回一个optional<Car> ,optPerson.map(function) ,因此 整体返回一个 Optional<Optional<Car>>,
因此调用getType()方法出错,因为getType()方法属于Car类,只有Optional<Car>可以调用
*
*/

class People{
    Optional<Car> car;
    public Optional<Car> getCar(){
        return car;
    }
}

class Car{
    Optional<Type> type;
    public Optional<Type> getType(){
        return type;
    }
}

class Type{
    double price ;
    public double getPrice(){
        return price;
    }
}

上述代码在运行的过程中会报错;

map方法的函数签名为:public <U> Optional<U> map(Function<? super T, ? extends U> mapper)

解决方式是:使用flatMap方法,flatMap方法接受一个函数作为参数,这个函数的返回值是另一个流,即flatMap会用流的内容替换每个新生成的流。就上面的例子分析,因为map也会将函数应用于流中的每个元素,但是它的流中的元素进行了包装,下次继续使用此流使调用map方法的时候,流中的元素已经不具备某些条件,因此我们需要的在经过了函数的调用后,返回的流的内容组成的新流;

因此,上面的代码可以改写为:

public double getCarPrice(Optional<People> people)
{
    return people.flatMap(People::getCar)
                 .flatMap(Car::getType)
                 .map(Type::getPrice)
                 .orElse(“Unknow”);
}

Optional的默认行为:

Optional类提供了多种方法读取Optional实例中的变量值:

get():如果变量存在,它直接返回封装的变量值,否则抛出异常;

orElse(T other):当对象不存在的时候,返回一个默认值;

orElseGet(Supplier<? extends T> supplier) 只有当Optional中不含值的时候才会被调用,

orElseThrow:当Optoinal对象为空的时候抛出一个异常,只不过这个异常可以进行定制;

ifPresent(): 判断值是否为空;

filter:筛选

Optional<T> filter(Predicate<? super T> predicate):使用filter可以进行Optional对象的筛选,他接受一个predicate接口的对象,返回一个boolean值,如果值为true,就将元素添加到Optional中。

内容参考《Java8 实战》 ,,由衷感谢此书作者为我们提供学习内容