java的可选链Optional

发布时间 2023-07-05 14:30:41作者: 看风景就

Optional是Jdk1.8提供的一个新类,用以解决null判断问题,作用类似于 JavaScript 中的可选链

例如如下场景:

private void getIsoCode(User user){
    if (user != null) {
        Address address = user.getAddress();
        if (address != null) {
            Country country = address.getCountry();
            if (country != null) {
                String isocode = country.getIsocode();
                if (isocode != null) {
                    isocode = isocode.toUpperCase();
                }
            }
        }
    }
    //可简化为
    Optional.ofNullable(user).map(u -> u.getAddress())
                             .map(a -> a.getCountry())
                             .map(c -> c.getIsoCode())
                             .map(c -> c.toUpperCase())
                             .orElse(null)
}

API介绍

Optional的所有的方法如下图所示,这些API大致可以分为以下几类:

1、构建API:构建一个Optional对象;方法有:empty( )、of( )、ofNullable( );

2、获取API:获取Optional对象里包装的值;方法有:get( )、orElse( )、orElseGet( )、orElseThrow( );

3、转换API:将Optional对象里包装的值转换成一个新的值;方法有:map( )、flatMap( );

4、判断API:对Optional对象里包装的值做一些逻辑判断;方法有:filter( )、isPresent( )、ifPresent( );

5. 创建Optional通常使用 Optional.ofNullable, 它能兼容null,进行连续处理

of(T value)的区别就是,当value值为null时,of(T value)会报NullPointerException异常
ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象


使用场景:

1. 仅仅在处理数据时使用,在方法内部处理数据
2. 不要将Optional作为 参数(含义模糊),成员变量(不可序列化)
3. 配合 Java Stream 使用效果最佳

 

以下为Optional<T>的正确使用方式:

//存在即返回, 无则提供默认值
return user.orElse(null);     //而不是 return user.isPresent() ? user.get() : null;

//存在即返回, 无则由函数来产生
return user.orElseGet(() -> getUser()); //而不要 return user.isPresent() ? user: getUser();

//存在才对它做点什么
user.ifPresent(System.out::println);
//而不要下边那样
if (user.isPresent()) {
  System.out.println(user.get());
}

//map处理返回空集合
return user.map(u -> u.getOrders()).orElse(Collections.emptyList())
//上面避免了我们类似 Java 8 之前的做法
if(user.isPresent()) {
  return user.get().getOrders();
} 
else {
  return Collections.emptyList();
}

//map无限级联, 比如再深一层, 获得用户名的大写形式
return user.map(u -> u.getUsername())
           .map(name -> name.toUpperCase())
           .orElse(null);

//filter支持对属性进行过滤
Optional<String> longName = name.filter((value) -> value.length() > 6);  
System.out.println(longName.orElse("The name is less than 6 characters"));


//Stream中使用
User user = users.stream().findFirst().orElse(new User("default", "1234"));

经典使用场景

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. 判断取值,无值返回特定值

public User getUser(User user){
    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;
                   });
}

3. 空值判断

if(user!=null){
    dosomething(user);
}
//可写为
Optional.ofNullable(user).ifPresent(u -> dosomething(u));
 
 
 

 

参考:Java8 Optional 的正确使用方式 

         还用 != null 判空?新姿势,值得学习