JDK8新特性之Optional
Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException),Optional<T>类在java.util包下,是一个容器类,它可以保存类型T的值,代表这个值存在;或者仅仅保存null,表示这个值不存在。原来用null表示一个值不存在,现在Optional可以更好的表达这个概念,并且可以避免空指针异常。
Optional类的javadoc描述如下:这是一个可以为null的容器对象,如果值存在则ispresent()会返回true,调用get()方法会返回该对象。
Optional类方法介绍
先创建一个People类,在接下来的测试中会用到该类
public class People {
private String name;
private int age;
private People friend;
public People() {
}
public People(String name, int age, People friend) {
this.name = name;
this.age = age;
this.friend = friend;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public People getFriend() {
return friend;
}
public void setFriend(People friend) {
this.friend = friend;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
", friend=" + friend +
'}';
}
}
创建Optional类对象的方法
- Optional.of(T t):创建一个Optional实例,t必须非空
- Optional.empty():创建一个空的Optional实例
- Optional.ofNullable(T t):t可以为null
@Test
public void test01(){
// Optional.of(T t):创建一个Optional实例,t必须非空
People people = new People();
people.setName("张三");
people.setAge(18);
// 如果这行代码放开运行会报NullPointerException错,因为people为Null
// people = null;
Optional<People> peopleOptional = Optional.of(people);
System.out.println(peopleOptional);// 结果:Optional[People{name='张三', age=18, friend=null}]
}
@Test
public void test02(){
// Optional.ofNullable(T t):t可以为null
People people = new People();
people.setName("李四");
people.setAge(22);
// 如果people=null,则
// people = null;
Optional<People> peopleOptional = Optional.ofNullable(people);
/**
* people不为空时结果:Optional[People{name='李四', age=22, friend=null}]
* people为空时的结果:Optional.empty
*/
System.out.println(peopleOptional);
}
@Test
public void test03(){
// Optional.empty():创建一个空的Optional实例
Optional emptyPeople = Optional.empty();
System.out.println(emptyPeople);// 结果:Optional.empty
/**
* Optional.empty()相当于将以前的null 包装了一下
* 以前是people == null
* 我们结合Optional.ofNullable来使用一下
*/
People people = null;
Optional<People> peopleOptional = Optional.ofNullable(people);
Optional<People> empty = Optional.empty();
if(peopleOptional == empty){
System.out.println("true");// 输出true
}
}
判断Optional容器是否包含对象
- boolean isPresent():判断是否包含对象
- void ifPresent(Consumer<? super T> consumer):如果有值,就执行consumer接口的实现代码,并且该值会作为参数传递给它
@Test
public void test04(){
// boolean isPresent():判断是否包含对象
People people = new People();
people.setName("李四");
people.setAge(22);
Optional<People> peopleOptional1 = Optional.ofNullable(people);
System.out.println(peopleOptional1.isPresent());// 结果:true
people = null;
Optional<People> peopleOptional2 = Optional.ofNullable(people);
System.out.println(peopleOptional2.isPresent());// 结果:false
// void ifPresent(Consumer<? super T> consumer):如果有值,就执行consumer接口的实现代码,并且该值会作为参数传递给它
// 加入People存在则取输出它的朋友信息
People people2 = new People("王五",23,new People("小明",21,null));
Optional<People> optionalPeople2 = Optional.ofNullable(people2);
optionalPeople2.ifPresent(p -> System.out.println(p.getFriend()));// 结果:People{name='小明', age=21, friend=null}
}
获取Optional容器的对象
- T get():如果调用对象包含值,返回该值,否则抛异常
- T orElse(T other):如果有值则将其返回,否则返回指定的other对象
- T orElseGet(Supplier<? extends T> other):如果有值则将其返回,否则返回由Supplier接口实现提供的对象
- T orElseThrow(Supplier<? extends X> exceptionSupplier):如果有值则将其返回,否则抛出由Supplier接口实现提供的异常
@Test
public void test05(){
// T get():如果调用对象包含值,返回该值,否则抛异常
People people = new People("詹姆斯",36,null);
// people = null;
Optional<People> optionalPeople = Optional.ofNullable(people);
// 当people为null时抛异常:java.util.NoSuchElementException: No value present
People result = optionalPeople.get();
System.out.println(result);// 结果是:People{name='詹姆斯', age=36, friend=null}
}
@Test
public void test06(){
People people = new People("詹姆斯",36,null);;
// people = null;
Optional<People> optionalPeople = Optional.ofNullable(people);
// T orElse(T other):如果有值则将其返回,否则返回指定的other对象
People result = optionalPeople.orElse(new People("韦德", 28, null));
/**
* people不为null时返回people:People{name='詹姆斯', age=36, friend=null}
* 为null时返回自己设置的默认对象:People{name='韦德', age=28, friend=null}
*/
System.out.println(result);
// T orElseGet(Supplier<? extends T> other):如果有值则将其返回,否则返回由Supplier接口实现提供的对象
People result2 = optionalPeople.orElseGet(() -> new People("保罗", 38, null));
/**
* people不为null时返回people:People{name='詹姆斯', age=36, friend=null}
* 为null时返回自己设置的默认对象:People{name='保罗', age=38, friend=null}
*/
System.out.println(result2);
}
@Test
public void test07(){
// T orElseThrow(Supplier<? extends X> exceptionSupplier):如果有值则将其返回,否则抛出由Supplier接口实现提供的异常
// 这里其实和上面的orElseGet有点类似,只不过这里是返回异常对象
// 这个主要是用于可以抛出指定异常
People people = new People("詹姆斯",36,null);;
people = null;
Optional<People> optionalPeople = Optional.ofNullable(people);
People result = optionalPeople.orElseThrow(() -> new RuntimeException("值不存在"));
System.out.println(result);
}
总结
Optional类主要的作用其实是为了消除空指针,虽然并不能完全消除但是给我们带来一些更方便的操作,比如为空时设置默认值,为空时抛出指定异常等。