java 只初始化一次_用Java 8实现懒初始化

用Java 8实现懒初始化

单例经常使用懒初始化,而且有时如果一个对象非常大且重量,那么其内部字段可以使用懒初始化的赋值方式。

通常getter方法内有一段代码是用来检查当前被获取的对象是否已经初始化,如果没有,那么就立即进行初始化,将初始化值赋予字段对象,一旦对象已经被初始化,这种检查就没有意义,是一次性的,它只会减慢方法的执行,特别是如果使用同步锁synchronized,下面我们看看如果去除这段只使用一次的代检查码,如下面案例:

Class A{

private B b;

public B getB(){

if (this.b == null)

this.b = new B(); //只使用一次的检查代码

return this.b

}

}

我们可以使用Java 8的函数编程方式来实现,其基本想法如下:

使用Supplier类型替代懒初始化字段

这个Supplier初始对象 (但是还不返回这个对象)

然后设置字段到新的Supplier,这个Supplier返回已经被初始化的对象

返回实例

看看下面的代码:

public class Holder

{

private Supplier heavy = () -> createAndCacheHeavy();

public Heavy getHeavy()

{

return heavy.get();

}

private synchronized Heavy createAndCacheHeavy()

{

class HeavyFactory implements Supplier

{

private final Heavy heavyInstance = new Heavy();

public Heavy get()

{

return heavyInstance;

}

}

if(!HeavyFactory.class.isInstance(heavy))

{

heavy = new HeavyFactory();

}

return heavy.get();

}

}

上面代码中可以正常实现懒初始化,但是createAndCacheHeavy代码有点比较复杂。做些修改如下:

private Heavy createAndCacheHeavy()

{

Heavy instance = new Heavy();

heavy = () -> instance;

return instance;

}

这比之前更加简单,为了使这个代码线程安全,需要同步getInstance()方法。

为了每次初始化时不必要建立createAndCacheHeavy这个类,我们可以做一个模板用来重用,这样只要如下调用即可:

Supplier heavy = LazilyInstantiate.using(() ->newHeavy());

让我们看看你这个LazilyInstantiate类模板做了些什么:

public class LazilyInstantiate implements Supplier

{

public static  LazilyInstantiate using(Supplier supplier)

{

return new LazilyInstantiate<>(supplier);

}

public synchronized T get()

{

return current.get();

}

private LazilyInstantiate(Supplier supplier)

{

this.supplier = supplier;

this.current = () -> swapper();

}

private final Supplier supplier;

private Supplier current;

private T swapper()

{

T obj = supplier.get();

current = () -> obj;

return obj;

}

}

更详细的源码库见:Github

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值