java的可选链Optional
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));