Lazy initialization - It decreases the cost of initializing a class or creating an instance, at the expense of increasing the cost of accessing the lazily initialized field. Depending on what fraction of lazily initialized fields eventually require initialization, how expensive it is to initialize them, and how often each field is accessed, lazy initialization can (like many "optimizations") actually harm performance.

The only way to know for sure is to measure the performance of the class with and without lazy initialization.

Principle

  • Normal initialization of an instance field - Under most circumstances, normal initialization is preferable to lazy initialization.

    // Normal initialization of an instance field

    private final FieldType field = computeFieldValue();

  • synchronized accessor - If you use lazy initialization to break an initialization circularity, use a synchronized accessor, as it is the simplest, clearest alternative:

    // Lazy initialization of instance field - synchronized accessor

    private FieldType field;

    synchronized FieldType getField() {

    if (field == null)

    field = computeFieldValue();

    return field;

    }

    Both of these idioms (normal initialization and lazy initialization with a synchronized accessor ) are unchanged when applied to static fields, except that you add the static modifier to the field and accessor declarations.

  • lazy initialization holder class idiom - If you need to use lazy initialization for performance on a static field, use the lazy initialization holder class idiom .

    // Lazy initialization holder class idiom for static fields

    private static class FieldHolder {

    static final FieldType field = computeFieldValue();

    }

    static FieldType getField() { return FieldHolder.field; }

  • Double-check idiom - If you need to use lazy initialization for performance on an instance field, use the double-check idiom.

    // Double-check idiom for lazy initialization of instance fields

    private volatile FieldType field;

    FieldType getField() {

    FieldType result = field;

    if (result == null) { // First check (no locking)

    synchronized(this) {

    result = field;

    if (result == null) // Second check (with locking)

    field = result = computeFieldValue();

    }

    }

    return result;

    }

  • Single-check idiom - Occasionally, you may need to lazily initialize an instance field that can tolerate repeated initialization.

    // Single-check idiom - can cause repeated initialization!

    private volatile FieldType field;

    private FieldType getField() {

    FieldType result = field;

    if (result == null)

    field = result = computeFieldValue();

    return result;

    }

    Note

    When the double- check or single-check idiom is applied to a numerical primitive field, the field's value is checked against 0 (the default value for numerical primitive variables) rather than null.

  • Racy single-check idiom - If you don't care whether every thread recalculates the value of a field, and the type of the field is a primitive other than long or double , then you may choose to remove the volatile modifier from the field declaration in the single-check idiom(e.g. String instances to cache their hash codes).

    // racy single-check idiom - can cause repeated initialization!

    private FieldType field;

    private FieldType getField() {

    FieldType result = field;

    if (result == null)

    field = result = computeFieldValue();

    return result;

    }

    Summary

    You should initialize most fields normally, not lazily. If you must initialize a field lazily in order to achieve your performance goals, or to break a harmful initialization circularity, then use the appropriate lazy initialization technique. For instance fields, it is the double-check idiom; for static fields, the lazy initialization holder class idiom. For instance fields that can tolerate repeated initialization, you may also consider the single-check idiom.

Effective Java 71 Use lazy initialization judiciously的更多相关文章

  1. Effective Java 54 Use native methods judiciously

    Java Native Interface(JNI) allows Java applications to call native methods, which are special method ...

  2. Effective Java Index

    Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...

  3. 《Effective Java》读书笔记 - 10.并发

    Chapter 10 Concurrency Item 66: Synchronize access to shared mutable data synchronized这个关键字不仅保证了同步,还 ...

  4. Effective Java 目录

    <Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...

  5. 【Effective Java】阅读

    Java写了很多年,很惭愧,直到最近才读了这本经典之作<Effective Java>,按自己的理解总结下,有些可能还不够深刻 一.Creating and Destroying Obje ...

  6. Effective Java通俗理解(下)

    Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...

  7. Effective java笔记(九),并发

    66.同步访问共享的可变数据 JVM对不大于32位的基本类型的操作都是原子操作,所以读取一个非long或double类型的变量,可以保证返回的值是某个线程保存在该变量中的,但它并不能保证一个线程写入的 ...

  8. 单例模式的两种实现方式对比:DCL (double check idiom)双重检查 和 lazy initialization holder class(静态内部类)

    首先这两种方式都是延迟初始化机制,就是当要用到的时候再去初始化. 但是Effective Java书中说过:除非绝对必要,否则就不要这么做. 1. DCL (double checked lockin ...

  9. Effective Java 阅读笔记——并发

    66:同步访问共享的可变数据 synchronized:1互斥,阻止线程看到的对象处于不一致的状态:2保证线程在进入同步区时能看到变量的被各个线程的所有修改 Java中,除了long或者double, ...

随机推荐

  1. [python]逆水行舟不进则退(1)

    工作后迎来的第一个长假期,打算在家休息一下,看看书之类的.但是不写点东西,不做点东西,感觉有些浪费时间.同时也想通过做点东西检验下自己这段时间的收获.其实在我开始写这篇文章的时候心里还是很没底的-交代 ...

  2. 敏捷个人微信号:AgileMe ,欢迎大家推广和关注

  3. Java魔法堂:初探MessageFormat.format和ChoiceFormat

    一.前言 刚开始从.net的转向java的时候总觉得 String.format 用得不习惯,希望格式模版会这样 {}, }$s,$s's cat.%2$s,this is %1$s's dog. . ...

  4. Vim杂记:markdown插件

    一.安装插件 从以下地址下载压缩包 github下载:https://github.com/plasticboy/vim-markdown plasticboy下载:http://plasticboy ...

  5. 对象Transform,对属性赋值

    private void ContructRequest(Dictionary<string, string> dictionary, CustomerSearchRequest requ ...

  6. 了解 JS 作用域与作用域链

    (1)作用域 一个变量的作用域(scope)是程序源代码中定义的这个变量的区域. 1. 在JS中使用的是词法作用域(lexical scope) 不在任何函数内声明的变量(函数内省略var的也算全局) ...

  7. JavaScrip

    一.JavaScript简介 1.JavaScript是个什么东西? 它是个脚本语言,需要有宿主文件,它的宿主文件是HTML文件. 2.它与Java什么关系? 没有什么直接的联系,Java是Sun公司 ...

  8. 重新想象 Windows 8.1 Store Apps (79) - 控件增强: MediaElement, Frame

    [源码下载] 重新想象 Windows 8.1 Store Apps (79) - 控件增强: MediaElement, Frame 作者:webabcd 介绍重新想象 Windows 8.1 St ...

  9. 晒自己做的一个管理系统(清新风格)EasyUI

    最近项目结束了,现在也要自己总结一下自己的成果了,总结会加深自己对项目的印象的.这里我就先晒一些作品图片了,希望大家看了会赞美一个! 项目虽然结束了,但是接下来的这个项目可就不是我一个人可以搞定的了, ...

  10. C#中的索引器原理

    朋友们,还记得我们在C#语言开发中用到过索引器吗? 记得在获得DataGridView控件的某列值时:dgvlist.SelectedRows[0].Cells[0].Value; 记得在获得List ...