Java Optional类

Posted june0816

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Optional类相关的知识,希望对你有一定的参考价值。

一、背景

1. Optional类主要解决空指针异常的问题,避免显式判断空指针,减少null的防御性检查

2. 借鉴了google guava的Optional类

3. Optinal类里有一个字段value,主要就是对value是否为Null的判断和操作

 

二、创建Optional类的实例,1个构造方法,3个静态方法

1. 构造方法 private Optional(T value),因为是私有的,不能被外部访问,也就不能调用构造方法创建对象,会报空指针异常

    private Optional(T value) 
        this.value = Objects.requireNonNull(value);
    

2. of()静态方法,底层调用私有构造方法,依然会报空指针异常

public static <T> Optional<T> of(T value) 
return new Optional<>(value);

Optional<String> optStr1 = Optional.of("optional");

3. empty()静态方法,不报空指针,返回一个值为null的Optional对象

public static<T> Optional<T> empty() 
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;

Optional<String> optStr = Optional.empty();

4. ofNullable()静态方法,底层调用empty()和of()方法,如果传入的值为null,就返回值为null的Optional对象,否则返回值不为null的Optional对象,建议使用

public static <T> Optional<T> ofNullable(T value) 
return value == null ? empty() : of(value);

Optional<String> optStr2 = Optional.ofNullable(null);

 

三、Optional的使用

1. get()方法,谨慎使用,返回包装对象的实际值,null会抛NoSuchElementException异常

 

2.isPresent() vs ifPresent()

isPresent()方法,谨慎使用,判断包装对象的实际值是否非空

ifPresent()方法,接收一个Consumer对象,如果值不为空,执行Consumer对象的accept()方法(有一个参数无返回值)

注意:千万不要这样写,因为仍然要判断null,跟不使用Optional没区别

User user = Optional.ofNullable(user);
if (Optional.isPresent())
   // TODO: do something

 

3. filter()方法,接收一个Predicate对象,即一个判断条件,用于对Optional对象进行过滤

Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);

 

4. map() vs flatMap() 用于值转换

map()方法,接收一个Function<? super T, ? extends U>对象,用Function函数进行计算

flatMap()方法,接收一个Function<? super T, Optional<U>>对象,用Function函数进行计算

 

5. orElse() vs orElseGet() vs orElseThrow()

orElse()方法,值为null,则返回默认值;即使值不为null,仍然会执行orElse(),不建议使用

orElseGet()方法,接收一个Supplier对象,用Supplier对象的get()方法作为默认值,当值不为null时,不会执行orElseGet(),建议使用

orElseThrow()方法,接收一个Supplier对象,Supplier对象必须返回一个异常

 

四、实际场景

1. 

public String getCity(User user)  throws Exception
        if(user!=null)
            if(user.getAddress()!=null)
                Address address = user.getAddress();
                if(address.getCity()!=null)
                    return address.getCity();
                
            
        
        throw new Excpetion("取值错误"); 


public String getCity(User user) throws Exception
    return Optional.ofNullable(user)
                   .map(u-> u.getAddress())
                   .map(a->a.getCity())
                   .orElseThrow(()->new Exception("取指错误"));

 

2. 

if(user!=null)
    dosomething(user);


Optional.ofNullable(user)
         .ifPresent(u->
            dosomething(u);
);

 

3. 

public User getUser(User user) throws Exception
    if(user!=null)
        String name = user.getName();
        if("zhangsan".equals(name))
            return user;
        
    else
        user = new User();
        user.setName("zhangsan");
        return user;
    


public User getUser(User user) 
    return Optional.ofNullable(user)
                   .filter(u->"zhangsan".equals(u.getName()))
                   .orElseGet(()-> 
                        User user1 = new User();
                        user1.setName("zhangsan");
                        return user1;
                   );

 

 

 

 

参考: 

https://www.jianshu.com/p/d81a5f7c9c4e

https://www.cnblogs.com/rjzheng/p/9163246.html

 

以上是关于Java Optional类的主要内容,如果未能解决你的问题,请参考以下文章

Java中的Optional类

Java8新特性:Optional类(超详解)

Java Optional 类

Java 8 Optional 类

Java8 新特性 Optional 类

Java8新特性Optional类