Optional的出现是为了解决java由来已久的null安全问题,正确的使用Optional会让你的代码写得十分优雅。
1.代码示例
import java.util.Optional;
public class OptionalMain {
/**
* User类
*/
private static class User {
/**
* 有参构造函数
*
* @param name
*/
public User(String name) {
this.name = name;
}
/**
* 名字
*/
private final String name;
public String getName() {
return name;
}
}
/**
* 1.8之前的写法
*
* @param user
* @return
*/
private static String getName1(User user) {
if (user == null) {
return "Unknow";
}
return user.getName();
}
/**
* Optional错误的写法
*
* @param user
* @return
*/
private static String getName2(User user) {
Optional<User> optionalUser = Optional.ofNullable(user);
if (!optionalUser.isPresent()) {
return "Unknow";
}
return optionalUser.get().getName();
}
/**
* Optional正确的使用姿势
*
* @param user
* @return
*/
private static String getName3(User user) {
return Optional.ofNullable(user).map(u -> u.getName()).orElse("Unknow");
}
/**
* 主函数
*
* @param args
*/
public static void main(String[] args) {
String name1 = getName1(null);
String name2 = getName2(null);
String name3 = getName3(null);
System.out.println(name1);
System.out.println(name2);
System.out.println(name3);
User user = new User("Zz");
name1 = getName1(user);
name2 = getName2(user);
name3 = getName3(user);
System.out.println(name1);
System.out.println(name2);
System.out.println(name3);
}
}
对比上面的代码,正确地使用Optional既能避免过多地null判断,同时让代码显得简短而优雅。
2.API分析
/**
* 无参构造函数默认value=null
*/
private Optional() {
this.value = null;
}
/**
* 直接通过构造函数的方式必须保证参数不为null
*
* @param value
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
/**
* 要求传入的参数不能为null
*
* @param value
* @param <T>
* @return
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
/**
* 默认value为null的Optional
*/
private static final Optional<?> EMPTY = new Optional<>();
/**
* 对外提供获取默认value为null的Optional
*
* @param <T>
* @return
*/
public static <T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
/**
* 根据代码逻辑判断,对参数没有限制,允许为null
*
* @param value
* @param <T>
* @return
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
从上述源码分析的角度来看,可以得出以下几个结论:
1.private的访问控制符意味着外界不能通过构造函数的方式创建
2.Optional.empty()可以直接创建一个value为空的Optional
3.Optional.of(T value)要求传的参数一定不能为null
4.Optional.ofNullable(T value)对参数是否为null没有限制
2.1Present的使用
import java.util.Optional;
public class OptionalMain {
private static void testPresent() {
Optional<String> optional1 = Optional.of("hello");
//如果value不是null,就会打印
optional1.ifPresent(System.out::println);
System.out.println(optional1.isPresent());
Optional<String> optional2 = Optional.ofNullable(null);
//如果value是null,就不会打印
optional2.ifPresent(System.out::println);
System.out.println(optional2.isPresent());
}
/**
* 主函数
*
* @param args
*/
public static void main(String[] args) {
testPresent();
}
}
2.2 orElse的使用
public class OptionalMain {
/**
* 测试Optional
*/
private static void testOptional() {
Optional<String> optional1 = Optional.ofNullable(null);
//如果value是null就返回hello
String res1 = optional1.orElse("hello");
System.out.println(res1);
//如果value是null就调用指定函数创建一个实例返回
String res2 = optional1.orElseGet(() -> new String("world"));
System.out.println(res2);
try {
//如果value是null抛出异常
optional1.orElseThrow(() -> new Exception("异常"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 主函数
*
* @param args
*/
public static void main(String[] args) {
testOptional();
}
}
2.3 filter的使用
import java.util.Objects;
import java.util.Optional;
public class OptionalMain {
/**
* User类
*/
private static class User {
/**
* 名字
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 有参构造函数
*
* @param name
* @param age
*/
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "name:" + name + " age:" + age;
}
}
/**
* 测试filter
*/
private static User isAdult(User user) throws Exception {
Optional<User> optional1 = Optional.ofNullable(user);
/**
* 过滤name不为null,age大于18岁的user
*/
return optional1.filter(u -> !Objects.isNull(u.getName()))
//年龄大于18岁
.filter(u -> u.getAge() > 18)
//如果name为null或者age小于18就抛出异常
.orElseThrow(() -> new Exception("未成年人"));
}
/**
* 主函数
*
* @param args
*/
public static void main(String[] args) throws Exception {
User user = isAdult(new User("Zz", 20));
System.out.println(user);
user = isAdult(new User("Z", 16));
System.out.println(user);
}
}
filter和数据库查询语句一样,以一种优雅的编码方式对数据进行过滤。
2.4 map的使用
import java.util.List;
import java.util.Optional;
public class OptionalMain {
/**
* User类
*/
private static class User {
/**
* 名字
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 有参构造函数
*
* @param name
* @param age
*/
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "name:" + name + " age:" + age;
}
}
/**
* 部门实体类
*/
private static class Department {
/**
* 部门名称
*/
private String name;
/**
* 部门领导
*/
private User leader;
/**
* 部门员工
*/
private List<User> users;
/**
* 有参构造函数
*
* @param name
* @param leader
* @param users
*/
public Department(String name, User leader, List<User> users) {
this.name = name;
this.leader = leader;
this.users = users;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public User getLeader() {
return leader;
}
public void setLeader(User leader) {
this.leader = leader;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
/**
* 测试map
*/
private static String getLeaderName(Department department) throws Exception {
Optional<Department> opt = Optional.ofNullable(department);
/**
* 从部门中查找领导名字
*/
return opt
//从部门中找出Leader
.map(dep -> dep.getLeader())
//从User中找出name
.map(leader -> leader.getName())
//如果name为null就抛出异常
.orElseThrow(() -> new Exception("没有领导"));
}
/**
* 测试flatMap
*/
private static String getUpperLeaderName(Department department) throws Exception {
Optional<Department> opt = Optional.ofNullable(department);
/**
* 从部门中查找领导名字
*/
return opt
//从部门中找出Leader
.map(dep -> dep.getLeader())
//从User中找出name
.map(leader -> leader.getName())
//flatMap相当于对流水线上的产品再做一次包装
.flatMap(name -> Optional.of(new User(name.toUpperCase(), 30)))
//从包装后的产品中再拆解
.map(leader -> leader.getName())
//如果name为null就抛出异常
.orElseThrow(() -> new Exception("没有领导"));
}
/**
* 主函数
*
* @param args
*/
public static void main(String[] args) throws Exception {
String leaderName = getLeaderName(new Department("部门名字", new User("部门领导名字", 30), null));
System.out.println(leaderName);
leaderName = getUpperLeaderName(new Department("部门名字", new User("leaderName", 30), null));
System.out.println(leaderName);
leaderName = getLeaderName(new Department("部门名字", null, null));
System.out.println(leaderName);
}
}
结束语:以上是关于Optional的一些简单实践。