jdk1.8中Optional的orElse与orElseGet

        最近正在梳理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)

观察运行结果,暂时得出:

  1. 当前Optional对象为空:OrElse/OrElseGet的方法体都执行了,最终返回由OrElse/OrElseGet产生的缺省值。
  2. 当前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函数式接口参数,具有延迟加载的特征,或者有的人也称为懒汉模式,

  1. orElse       :不管当前Optional对象是否为空,方法都要运行,并且会把Other方法体载入内存。
  2. orElseGet :不管当前Optional对象是否为空,方法都要运行,只有在当前Optional为空的时候,才会载入Supplier<? extends T> other的实现。
  3. 当我们在高并发的系统里面,为了避免产生空对象,设置缺省值时,建议使用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的区别了吧

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值