一、前言
我们在编程中经常会进行空指针判断,常用if
来完成,这会让代码非常冗余,像下面这样:
/**
* 获取用户所在的城市
*
* @param user 用户
* @return 城市的大写
*/
public static String getCity(User user) throws Exception {
// return user.getAddress().getCity().toUpperCase(Locale.ENGLISH);//这写法存中空指针问题
if (user != null) {
Address address = user.getAddress();
if (address != null) {
if (address.getCity() != null) {
return address.getCity().toUpperCase(Locale.ENGLISH);
}
}
}
throw new Exception("有空指针");
}
// Lombok构造实体类
@Data
@Builder
class User {
private String name;
private Address address;
}
@Data
@Builder
class Address {
private String city;
}
我们想取用户的大写地址,需要进行多重判断,代码进行了多次缩进,看着也不美观。Optional因此而生。
二、Optional类
optional类是jdk8引入的,主要是为了解决空指针问题。optional本质是一个容器,把值放入容器中,可以规避空指针问题。官方解释如下:
这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
此类的常用方法如下:
-
get()
:如果 Optional中有一个值,返回值,否则抛出 NoSuchElementException 。 -
ifPresent(Consumer<? super T> consumer)
:如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。 -
map(Function<? super T, ? extends U> mapper)
:如果存在一个值,则应用提供的映射函数,如果结果不为空,则返回一个 Optional结果的 Optional 。 -
ofNullable(T value)
:返回一个 Optional指定值的Optional,如果非空,则返回一个空的 Optional 。 -
orElse(T other)
:返回值如果存在,否则返回 other -
orElseGet(Supplier<? extends T> other)
:返回值(如果存在),否则调用 other并返回该调用的结果。
三、改进与总结
重写getCity()方法,暂且命名getCity2(),具体如下:
public static String getCity2(User user) throws Exception {
return Optional.ofNullable(user)
.map(User::getAddress)
.map(address -> address.getCity().toUpperCase(Locale.ENGLISH))
.orElseThrow(() -> new Exception("有空指针"));
}
public static void main(String[] args) {
User user = User.builder().name("ZS").address(Address.builder().city("beijing").build()).build();
User user1 = null;
User user2 = User.builder().name("ZS").address(null).build();
// 1、传统形式及结果
try {
System.out.println(getCity(user));// BEIJING
//System.out.println(getCity(user1)); // 有空指针
System.out.println(getCity(user2)); // 有空指针
} catch (Exception e) {
e.printStackTrace();
}
// 2、optional形式及结果
try {
System.out.println(getCity2(user));// BEIJING
//System.out.println(getCity2(user1)); // 有空指针
System.out.println(getCity2(user2)); // 有空指针
} catch (Exception e) {
e.printStackTrace();
}
}
其实他的功能不仅如此,比如我要获取用户的姓名,如果传来的user=null,则返回一个默认用户。下面一起看看传统形式与optional形式。
/**
* 获取用户名,如果是空,则返回默认名
*
* @param user 用户
* @return 用户名
*/
public static String getName(User user) {
// 1、传统形式
if (user != null) {
return user.getName();
} else {
return "默认用户名:张三";
}
// 2、Optional形式
return Optional.ofNullable(user).map(User::getName).orElse("默认用户名:张三");
}
可以看到,原本需要四行代码完成的逻辑,如今只需要一行了,变更更简洁了。
获取更多内容,请关注微信公众号。搜索“码圈小橙子”,这里会不时的更新。