jdk1.8中Optional的orElse与orElseGet
程序员文章站
2022-06-04 19:20:55
...
最近正在梳理jdk1.8的新特征,正好整理到orElse/orElseGet方法,因为平时用的不多,就在网上查了一些资料,众说纷纭啊
好多人说的和运行结果还不一致,岂可修!!
废话少说,这里把我最终获得的结果贴在这,防止忘记。下面是测试用例。代码里面有一个Product类,不贴了,就是个普通的formbean类,有一个带参数的构造方法。
@Test
public void test_orElse() {
System.out.println("================optional源对象空====================");
Product pro=null;
Product op3=Optional.ofNullable(pro).orElse(createPro());
System.out.println(op3);
Product op4=Optional.ofNullable(pro).orElseGet(()->{
System.out.print("in orElseGet:");
return new Product("orElseGet Create");
});
System.out.println(op4);
System.out.println("===================optional源对象不空==================");
Product pro1=new Product("源对象");
Product op23=Optional.ofNullable(pro1).orElse(createPro());
System.out.println(op23);
Product op24=Optional.ofNullable(pro1).orElseGet(()->{
System.out.print("in orElseGet:");
return new Product("orElseGet Create");
});
System.out.println(op24);
}
public Product createPro() {
System.out.print("in orElse:");
return new Product("orElse Create");
}
运行结果:
================optional源对象空====================
in orElse:Product(code=null, name=orElse Create, price=null, color=null, deleted=0)
in orElseGet:Product(code=null, name=orElseGet Create, price=null, color=null, deleted=0)
===================optional源对象不空==================
in orElse:Product(code=null, name=源对象, price=null, color=null, deleted=0)
Product(code=null, name=源对象, price=null, color=null, deleted=0)
观察运行结果,暂时得出:
- 当前Optional对象为空:OrElse/OrElseGet的方法体都执行了,最终返回由OrElse/OrElseGet产生的缺省值。
- 当前Optional对象不为空:OrElse的方法体执行了,OrElseGet方法体没有执行,最终返回Optional对象本身。
网上大部分结论都总结到此,一些反对的声音,主要集中在 Optional对象不空的时候,orElseGet到底执行不执行。 我们来看一下源代码,最有说服力。
/**
* Return the value if present, otherwise return {@code other}.
*
* @param other the value to be returned if there is no value present, may
* be null
* @return the value, if present, otherwise {@code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}
/**
* Return the value if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code Supplier} whose result is returned if no value
* is present
* @return the value if present otherwise the result of {@code other.get()}
* @throws NullPointerException if value is not present and {@code other} is
* null
*/
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
我们可以看到两个方法体,都是一个三元表达式,对value进行了判空,如果空的情况下,进行other处理。所以说,其实不管当前Optional对象是否为空,orElse/orElseGet方法肯定是都要运行的。不同的是,OrElseGet的入参是Supplier函数式接口参数,具有延迟加载的特征,或者有的人也称为懒汉模式,
- orElse :不管当前Optional对象是否为空,方法都要运行,并且会把Other方法体载入内存。
- orElseGet :不管当前Optional对象是否为空,方法都要运行,只有在当前Optional为空的时候,才会载入Supplier<? extends T> other的实现。
- 当我们在高并发的系统里面,为了避免产生空对象,设置缺省值时,建议使用orElseGet,减轻内存负担。
PS,说来说去,其实本质都不是说Optional里面OrElse/OrElseGet有所区分,而是传统的传参和函数式参数的区别。了解jdk1.8中函数式接口的大佬可以关闭本文了。不了解接口参数的,我举个栗子放这大家尝尝。
//传统写法,参数是基础数据类型或对象
public String doGet(String param) {
return "doGet:"+param;
}
//生成数据的服务方法
public String createStr() {
System.out.println("do create");
return "use function";
}
//jdk1.8中,方法参数可以是接口
public String supplierDoGet(Supplier<String> nameOption) {
return "doSupplierGet: "+nameOption.get();
};
public String supplierNotDoGet(Supplier<String> nameOption) {
return "notDoGet";
};
@Test
public void test() {
System.out.println("==============================传统写法===============================");
System.out.println(doGet(createStr()));
System.out.println("==========方法参数是函数式接口参数,方法体内执行Suppliler接口的get方法============");
System.out.println(supplierDoGet(()->{
System.out.println("|接口实现方法体,生成数据|");
return "use supplier";
}));
System.out.println("==========方法参数是函数式接口参数,方法体内不执行Suppliler接口的get方法============");
System.out.println(supplierNotDoGet(()->{
System.out.println("|接口实现方法体,生成数据|");
return "use supplier";
}));
}
运行结果:
==============================传统写法===============================
do create
doGet:use function
==========方法参数是函数式接口参数,方法体内执行Suppliler接口的get方法============
|接口实现方法体,生成数据|
doSupplierGet: use supplier
==========方法参数是函数式接口参数,方法体内不执行Suppliler接口的get方法============
notDoGet
上面的例子,写了三种使用情况,通过运行结果,我们不难类比orElse/orElseGet的区别了吧
上一篇: CentOS6上安装Subversion
下一篇: jdk1.8中arrayList源码解析