1. Optional 出现的意义
Optional 是从 JDK1.8 开始提供的一个容器类, 主要用于避免空指针异常(NPE), 其提供的一系列方法配合 Lambda 表达式可以让代码更加清晰, 语义化, 以及避免了空指针异常的问题这里要注意是避免空指针异常, 而不是避免返回null.
2.Optional的常用api
- Optional.of() :创建一个Optional实例,但是传入null会报空指针异常
- Optional.empty() :创建一个空的Optional实例
- Optional.ofNullable(T t) :如果t不为空,则创建Optional实例,如果为null则创建一个空的Optional实例
- isPresent() : 判断是否包含值
- orElse(T t) : 如果调用的对象包含值则返回该值,否则返回t
- orElseGet(Supplier s) :如果调用的对象包含值则返回该值,否则返回s获取的值。
- map(Function f) : 如果有值,对其处理。并返回处理后的Optional,否则返回Optional.empty();
- flatMap(Function f) : 与map相似,要求f返回的值必须是Optional.
3.代码验证
- Optional.of()
/**
* 创建一个Optional实例,但是传入null会报空指针异常
*/
public static void testOf(){
Optional<Employee> employee = Optional.of(new Employee());
System.out.println( employee.get());
System.out.println("-------------------");
// 传入nul直接报空指针异常
Optional<Employee> employee1 = Optional.of(null);
}
- Optional.empty()
/**
* 创建一个空的Optional实例
*/
public static void testEmpty(){
Optional<Employee> empty = Optional.empty();
//返回一个空的Optional,如果调用他的get方法会报空指针。
System.out.println(empty.get());
}
- Optional.ofNullable(T t)
此方法是of()和empty()的结合,建议使用此方法生成Optional对象
/**
* 如果t不为空,则创建Optional实例,如果为null则创建一个空的Optional实例
*/
public static void ofNullable(){
// 如果参数传null,则底层调用empty方法,否则底层调用of方法。
Optional<Employee> employee = Optional.ofNullable(new Employee()); // 调用of方法
System.out.println(employee.get());
System.out.println("-----------------");
Optional<Employee> employee1 = Optional.ofNullable(null); // 调用empty方法
// 由于是空的Optional所有这一句报空指针异常。
System.out.println(employee1.get());
}
- isPresent()
/**
* 判断是否包含值
*/
public static void testIsPresent(){
Optional<Employee> employee = Optional.ofNullable(null);
if (employee.isPresent()){
// 此时得到一个空的Optional,经过isPresent判断后为false所有不会执行这一句。
System.out.println(employee.get());
}
}
- orElse(T t)
/**
* 如果调用的对象包含值则返回该值,否则返回t
*/
public static void testOrElse(){
Optional<Employee> employee = Optional.ofNullable(null);
Employee employee1 = employee.orElse(new Employee());
System.out.println(employee1);
}
- orElseGet(Supplier s)
此方法和orElse相似,不过这个方法可以的参数可以传入一个表达式,在表达式中可以做任何事情,相比orElse方法更为灵活
/**
* 如果调用的对象包含值则返回该值,否则返回s获取的值。
*
*/
public static void testOrElseGet(){
Optional<Employee> employee = Optional.ofNullable(null);
Employee employee1 = employee.orElseGet( () -> {
System.out.println("---");
return new Employee();});
System.out.println(employee1);
}
- map(Function f)
这个方法传入一个函数型接口Function的实现,返回一个Option
/**
* 如果有值,对其处理。并返回处理后的Optional,否则返回Optional.empty();
*/
public static void testMap(){
Optional<Employee> employee = Optional.ofNullable(new Employee("吴国庆",29,999.999));
Optional<String> s = employee.map(TestOptional::test);
System.out.println(s.get());
}
public static String test(Employee employee){
return employee.getName();
}
- flatMap(Function f)
这个方法和map方法比较类似,不同的时这个方法的Function接口的实现需要返回一个Option对象,而map方法则可以返回任意对象,这样就可以在实现类中对获取到的数据继续做一次判空。
/**
* 与map相似,要求f返回的值必须是Optional.
*/
public static void testFlatMap(){
Optional<Employee> employee = Optional.ofNullable(new Employee("吴国庆",29,999.999));
Optional<String> s = employee.flatMap(TestOptional::test1);
System.out.println(s.orElse("张三"));
}
public static Optional<String> test1(Employee employee){
return Optional.ofNullable(employee.getName());
}
Employee类
public class Employee {
String name;
Integer age;
Double salary;
Status status;
public Employee(){
}
public Employee(String name, Integer age, Double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public Employee(String name, Integer age, Double salary, Status status) {
this.name = name;
this.age = age;
this.salary = salary;
this.status = status;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
if (name != null ? !name.equals(employee.name) : employee.name != null) return false;
if (age != null ? !age.equals(employee.age) : employee.age != null) return false;
if (salary != null ? !salary.equals(employee.salary) : employee.salary != null) return false;
return status == employee.status;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (age != null ? age.hashCode() : 0);
result = 31 * result + (salary != null ? salary.hashCode() : 0);
result = 31 * result + (status != null ? status.hashCode() : 0);
return result;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
", status=" + status +
'}';
}
public enum Status{
FREE,
BUSY,
VOCATION;
}
}