我相信,每一个Java程序员都必然会遇到过这样一个异常:NullPointerException(NPE),空指针异常。这个异常让我们很痛疼,如果写的代码不够鲁棒,导致尝试访问空对象的方法或字段时就会抛出这个异常。
因此合格的程序员都会在使用对象前进行判空,常见的是用if条件判断,如果对象不为空则可以继续进行访问对象字段和方法的操作,如果对象为空那么不可以进行访问对象的字段和方法的操作。常用编程范式如下:
public void printUserName(User user) {
if (user == null) {
return;
}
System.out.println(user.getName());
}
大量的这种重复逻辑的代码显得十分不优雅~,于是在Java8中JDK很贴心地为我们提供了更优雅的处理方式:借助Optional类,帮助我们从if判空的桎梏中解脱出来。
熟悉Optional
1.1 通过一个demo了解Optional用法
如果不清楚API也不要紧,先大概了解一下用法,后面我会详细介绍API的
User user = new User("zhanghaobo");
// 创建一个Optional对象,里面内容是user
Optional<User> optional = Optional.ofNullable(user);
optional.ifPresent(
user1 -> {
System.out.println("user对象非空!");
System.out.println(user1.getUsername());
}
);
这段代码的输出是:
user对象非空!
zhanghaobo
使用了ifPresent这个函数,意思是如果optional这个对象里面不为空,才会执行lambda表达式的语句,否则就不执行。
这样看起来是不是很清爽了,根本不需要我们再去每次if判断了。十分优雅~
那接下来我们就看看Optional类相关的API吧
1.2 创建Optional对象
①使用静态方法 empty() 创建一个内容为空的Optional 对象
Optional<User> empty = Optional.empty();
System.out.println(empty);
// 输出:Optional.empty
②使用静态方法 of() 创建一个内容不为空的Optional 对象
User user = new User("zhanghaobo");
Optional<User> optional = Optional.of(user);
//输出:Optional[User{username='zhanghaobo'}]
③使用静态方法 ofNullable() 创建一个内容既可空又可非空的 Optional 对象
User notnull = new User("zhanghaobo");
User isnull = null;
Optional<User> notNullOptional = Optional.ofNullable(notnull);
Optional<User> isnullOptional = Optional.ofNullable(isnull);
System.out.println(notNullOptional); //输出:Optional[User{username='zhanghaobo'}]
System.out.println(isnullOptional); //输出:Optional.empty
1.3 判断对象是否存在?
通过 isPresent()方法判断一个 Optional 对象内部的值是否存在,如果存在,则该方法返回 true,如果不存在,则返回 false。不用再写 user != null 这种判空了。
User user = new User("zhanghaobo");
Optional<User> optional = Optional.ofNullable(user);
System.out.println(optional.isPresent()); //true
User nullUser = null;
Optional<User> optionalNull = Optional.ofNullable(nullUser);
System.out.println(optionalNull.isPresent()); //false
1.4 非空表达式
我们知道Java8中有很多新特性,其中包括函数式接口、lambda表达式、流式操作等,提供这些特性以支持函数式编程。
Optional类中的ifPresent()方法在optional对象里面的值不为空的情况下允许我们使用函数式编程的方式执行一些代码,而当optional对象里面的值为空时则不会执行,因此,我把它称为非空表达式。如果没有该方法的话,我们通常需要先通过 isPresent() 方法对 Optional 对象进行判空后再执行相应的代码,而现在我们可以这么写:
User user = new User("zhanghaobo");
Optional<User> optional = Optional.ofNullable(user);
optional.ifPresent(user2 -> {
System.out.println("User对象非空,username is :" + user.getUsername());
});
输出为:
User对象非空,username is :zhanghaobo
如果user是null的话,将不会执行ifPresent里面的lambda表达式。
tips:Java 9 后还可以通过方法 ifPresentOrElse(action, emptyAction) 执行两种结果,非空时执行 action,空时执行 emptyAction。
1.5 获取or设置默认值
有这样的一些场景,如果Optional对象里面的值为空,那么返回一个默认值。
这时候可以使用orElse方法。
User user = null;
User realUser = Optional.ofNullable(user).orElse(new User("zhanghaobo"));
System.out.println(realUser); //输出:User{username='zhanghaobo'}
User user1 = new User("lisi");
User realUser1 = Optional.ofNullable(user1).orElse(new User("zhanghaobo"));
System.out.println(realUser1); //输出:User{username='lisi'}
从上面的demo可以看出:
orElse() 方法返回 Optional 对象中包含的值,如果该值不为 null,则返回;否则返回默认值。该方法的参数类型和值的类型一致。
orElseGet() 方法与 orElse() 方法类似,但参数类型不同。如果 Optional 对象中的值为 null,则执行参数中的函数。
User user = null;
User realUser = Optional.ofNullable(user).orElseGet(() -> {
return new User("zhanghaobo");
});
System.out.println(realUser); //输出:User{username='zhanghaobo'}
那orElse和orElseGet有什么区别呢?看如下代码:
User user = new User("zhanghaobo");
User orElse = Optional.ofNullable(user).orElse(getDefaultUser());
System.out.println("#############");
User orElseGet = Optional.ofNullable(user).orElseGet(OptionalDemo::getDefaultUser);
}
public static User getDefaultUser() {
System.out.println("invoke getDefaultUser method");
return new User("lisi");
}
输出为:
invoke getDefaultUser method
#############
证明orElseGet的参数不一定会被执行,所以性能会比orElse好。
1.6 值过滤--filter
对Optional对象中包含的值进行过滤,如果满足filter函数参数的lambda表达式中的条件,则返回此Optional对象,如果不满足条件,则返回Optional.empty。
User user = new User("zhanghaobo");
Optional<User> optionalUser = Optional.ofNullable(user).filter(user1 -> {
return user1.getUsername().equals("lisi");
});
System.out.println(optionalUser); //输出:Optional.empty
1.7 数据转换--map
使用map可以对Optional中包含的值进行一些转换操作。比如下面的demo,就是把user变成了一个新的user。
User user = new User("zhanghaobo");
Optional<User> optionalUser = Optional.ofNullable(user).map(user1 -> {
return new User("lisi");
});
System.out.println(optionalUser); //输出:Optional[User{username='lisi'}]
网友评论