一、Optiona容器类说明
Optional类(java.util.Optional)是一个容器类,代表一个值存在或不存在,原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常。
二、Optional容器类常用方法说明
常用方法:
Optional.of(T t):创建一个Optional实例
Optional.empty():创建一个空的Optional实例
Optional.ofNullable(T t):若t不为null,创建Optional实例,否则创建空的实例
isPresent():判断是否包含值
orElse(T t):如果Optional实例包含值,返回该值,否则返回t
orElseGet(Supplier s):如果Optional实例包含值,返回该值,否则返回s获取的值
map(Function f):如果有值对其处理,并返回成立后的Optional,否则返回Optional.empty()
flatMap(Function mapper):与map类似,要求返回值必须是Optional
三、Optional部分容器类的源码分析
//这是Optional类中的两个变量
//EMPTY表示一个空的Optional实例,所包含的值为null
private static final Optional<?> EMPTY = new Optional<>();
//Optional实例所包含的值
private final T value;
private Optional() {
this.value = null;
}
//创建一个空的Optional实例
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
//创建一个Optional实例
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
//若t不为null,创建Optional实例,否则创建空的实例
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
//得到Optional类实例所包含的值
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
//判断是否包含值
public boolean isPresent() {
return value != null;
}
//如果有值对其处理,并返回成立后的Optional,否则返回Optional.empty()
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
//与map类似,要求返回值必须是Optional
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
//如果Optional实例包含值,返回该值,否则返回t
public T orElse(T other) {
return value != null ? value : other;
}
//如果Optional实例包含值,返回该值,否则返回s获取的值
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
四、演示
public class OptionalAPI {
@Test
public void test01(){
//Optional.of(T t):创建一个Optional实例
Optional<Employee> optional = Optional.of(new Employee());
Employee employee = optional.get();
System.out.println(employee);
}
@Test
public void test02(){
//Optional.ofNullable(T t):若t不为null,创建Optional实例,否则创建空的实例
Optional<Object> optional = Optional.ofNullable(null);
//isPresent():判断是否包含值
if (optional.isPresent()){
System.out.println("值是:"+optional.get());
}
//orElse(T t):如果调用对象包含值,返回该值,否则返回t
System.out.println(optional.orElse(new Employee("张三",22,9999.99)));
//orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回s获取的值
Employee o = (Employee) optional.orElseGet(Employee::new);
System.out.println(o);
}
@Test
public void test03(){
//map(Function f):如果有值对其处理,并返回成立后的Optional,否则返回Optional.empty()
Optional<Employee> optional = Optional.of(new Employee("张三", 22, 9999.99));
Optional<String> optionalS = optional.map(Employee::getName);
System.out.println(optionalS.get());
//flatMap(Function mapper):与map类似,要求返回值必须是Optional
Optional<String> stringOptional = optional.flatMap((e) -> Optional.of(e.getName()));
System.out.println(stringOptional.get());
}
}
五、在真实的场景中使用Optional类
例如:每个男人心中都有一个女神,每个女神都有一个名字。但是不是每个男人心中都有女神,有可能他们心中有男神,也有可能什么都没有,但是每一个女神肯定都有名字。
根据上面的场景就得出两个类:
public class Man {
private Godness godness;
public Man(){}
public Godness getGodness() {
return godness;
}
public void setGodness(Godness godness) {
this.godness = godness;
}
}
public class Godness {
private String name;
public Godness(){
}
public Godness(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
现在我想根据一个男人得到他的女神的名字,但是这个男人根本没有女神,然后就会得到空指针异常。
public void test(){
Man man = new Man();
String name = getGodnessName1(man);
System.out.println(name);
}
//原始解决办法
private String getGodnessName1(Man man){
if (man != null){
Godness godness = man.getGodness();
if (godness != null){
return godness.getName();
}
}
return "苍老师";
}
//用Optional类解决办法
private String getGodnessName2(Optional<Man> man){
return Optional.ofNullable(man.orElse(new Man()).getGodness())
.orElse(new Godness("苍老师"))
.getName();
}
//这就是另外一种解决方法
private String getGodnessName3(Optional<NewMan> newMan){
return newMan.orElse(new NewMan())
.getGodness()
.orElse(new Godness("苍老师"))
.getName();
}
还有一种解决办法,就是直接在Man类中把Godness用Optional类封装起来
public class NewMan {
private Optional<Godness> godness=Optional.empty();
public NewMan(){}
public Optional<Godness> getGodness() {
return godness;
}
public void setGodness(Optional<Godness> godness) {
this.godness = godness;
}
}