欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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)

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

  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的区别了吧

 

相关标签: java