延迟初始化(lazy initialization),也就是在真正被使用的时候才开始初始化的技巧。

不论是静态还是实例,都可以进行延迟初始化。

其本质是初始化开销和访问开销之间的权衡。

毕竟是一种优化技巧,使用不当会起反效果。

尤其是在多线程场景中这种反效果会尤为明显,因为我们要对这个进行延迟初始化的field进行同步。

先一步步开始,如果初始化开销不值一提,我们只需要保证其不可变即可:

private final FieldType field1 = computeFieldValue();

如果还有的商量,初始化开销可能让人在意,下面是最简单的的方式,直接在访问方法声明里加了synchoronized修饰,这种方式将访问开销最大化了:

private FieldType field2;

synchronized FieldType getField2() {

if (field2 == null)

field2 = computeFieldValue();

return field2;

}

private static FieldType computeFieldValue() {

return new FieldType();

}

如果要改为静态的也不过是加上static修饰,但对于静态初始化,我们可以使用class holder方式:

private static class FieldHolder {

static final FieldType field = computeFieldValue();

}

static FieldType getField3() {

return FieldHolder.field;

}

private static FieldType computeFieldValue() {

return new FieldType();

}

这种方式感觉不错,我们没有进行额外的同步处理,只有在访问getField3的时候FieldHolder才会被初始化。

所以这种情况属于没有增加访问开销也保证了延迟特性。

这次试试优化一下实例field的访问开销,最经典的就是double-check了,这个东西经常出现在笔试题中:

private volatile FieldType field4;

FieldType getField4() {

FieldType result = field4;

if (result == null) {

synchronized (this) {

result = field4;

if (result == null)

field4 = result = computeFieldValue();

}

}

return result;

}

private static FieldType computeFieldValue() {

return new FieldType();

}

代码中使用了result局部变量,这样做虽然不是必要的,但这样可以确保field已被初始化的情况下被读取一次,可以提高少许效率。

以上就是延迟初始化的一些常用方式。

延迟初始化看起来不错,但建议权衡访问和创建的开销,对于实例field使用double-check,对于静态field使用holder class,以在多线程访问时保证check-then-action的原子性。

java 延迟初始化_Java - 延迟初始化相关推荐

  1. java 中的惰性初始化_java惰性初始化

    初始化有效地实现了尽可能的惰性.仅使用.class语法来获得对类的引用不会引发初始化.但是为了产生Class引用,Class.forName() 立即就进行了初始化 如果一个static final值 ...

  2. java 对象初始化_Java对象初始化

    自动初始化(默认值) 一个类的所有基本数据成员都会得到初始化,运行下面的例子可以查看这些默认值: classDefault{booleant;charc;byteb;shorts;inti;longl ...

  3. java类型的数组初始化_java数组初始化详解

    介绍 学习Java的朋友想必对数组并不陌生,它需要使用之前对其进行初始化,这是因为数组是引用类型,声明数组只是声明一个引用类型的变量,并不是数组对象本身,只要让数组变量指向有效的数组对象,程序中就可使 ...

  4. java静态实例初始化_Java静态初始化,实例初始化以及构造方法

    Java静态初始化,实例初始化以及构造方法 首先有三个概念需要了解: 一.静态初始化:是指执行静态初始化块里面的内容. 二.实例初始化:是指执行实例初始化块里面的内容. 三.构造方法:一个名称跟类的名 ...

  5. java程序初始化_Java程序初始化顺序

    今天在课上复习了Java的初始化顺序,一直有点疑惑,搞不明白,所以打算写下来,记录一下. 先说一下Java程序初始化的顺序:父类静态变量>父类静态代码块>子类静态变量>子类静态代码块 ...

  6. java 未初始化_Java中初始化问题

    一.普通类(无继承)的初始化顺序: java编程思想中,对一个对象的创建过程总结如下,假设有一个名为Dog的类: 1.即使没有显示的使用static关键字,构造器实际上也是静态方法.因此当首次创建一个 ...

  7. java数组怎么全部初始化_Java数组初始化,这三种方式有什么区别?

    首先因为数组初始化要使用的时候必须确定数组的长度,也就是说数组的长度是不可变的. 在JAVA中创建数组有两种方式 : (1)静态创建 如 Object[] arr1 = {"a", ...

  8. java arraylist静态初始化_Java 中初始化 List 集合的 6 种方式!

    1.常规方式 List languages = new ArrayList<>(); languages.add("Java"); languages.add(&quo ...

  9. java数组初始_java数组初始化的三种方式

    第一种方式:通过给定数组长度来赋值: public static void main(String[] args) { // TODO Auto-generated method stub //第一种 ...

最新文章

  1. BasicLSTMCell中num_units参数解释
  2. 我们学校的DV作品——《感悟青春》
  3. 面对滚滚而来好政策 安防行业该如何发展
  4. 预处理器命令必须作为第一个非空白空间启动_第三章 图形处理器(上)
  5. python一次删除多个键值对_Python单击:多个键值对参数
  6. 《Python参考手册(第4版•修订版)》——1.4 文件输入和输出
  7. [转]解决Windows 7下Windows Live Messenger(MSN) 9.0在一直停靠任务栏而不在系统栏显示的问题...
  8. Eclipse中要导出jar包中引用了第三方jar包怎么办
  9. stm32 isp下载官方软件android_OpenCanvas免费版下载_OpenCanvas绘图软件官方版下载7.0.25...
  10. react hooks_为什么选择React Hooks,我们如何到达这里?
  11. 【2】PRD文档介绍
  12. 链表的常见操作(转)
  13. Feature Scaling(特征缩放)的一些方法和使用选择
  14. rs232 linux驱动程序,rs232驱动,USB-RS232驱动程序安装说明
  15. 专科学校计算机是必修课吗,高等专科学校公共计算机选修课的开展与探索
  16. C++中read和write的区别
  17. SpringBoot中Redis报错:NOAUTH Authentication required.; nested exception is redis.clients.jedis.exceptio
  18. 苹果手机通话记录删除了怎么恢复?
  19. 吐血推荐 36招搞定电脑一切难题
  20. teamviewer远程黑屏问题

热门文章

  1. tensorflow入门之损失函数
  2. Environment.CurrentDirectory 的一个坑
  3. 存储过程或视图的字符串查询
  4. 面向对象的软件工程应用浅研
  5. 0b3398php,思想道德修养与法律基础(九江职业技术学院)知到2020题目及答案
  6. python算法与数据结构-选择排序算法
  7. mysql全量备份、增量备份实现方法
  8. sublime text2/3怎样在windows中配置ctags插件
  9. ElementUI的el-form表单验证报错[Element Warn][Form]model is required for validate to work!
  10. 反思编写页面追加页面元素的方法,目的:加快开发速度 节省开发时间 需求:点击搜索清空表格内容进行增加新的数据行