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. Java魔法堂:JUnit4使用详解

    目录                                                                                              1. 开 ...

  2. [Bootstrap]7天深入Bootstrap(3)CSS布局

    Bootstrap三大核心内容的基础,即基础的CSS 布局语法.其包括基础排版(Typography).代码(Code).表 格(Tables).表单(Forms).按钮(Buttons).图片 (I ...

  3. Sprint第三个冲刺(第四天)

    一.Sprint介绍 任务进度: 二.Sprint周期 看板: 燃尽图:

  4. Unity多语言本地化改进版

    简介 之前捣鼓过一个通过csv配置游戏多语言支持的小工具,但是发现使用过程中,通过notepad++去进行转码很不方便,并且直接将配置的csv不加密的放在游戏中心里感觉不是很踏实 于是乎~~ 新的方案 ...

  5. MessageFormat格式化的一些问题

    如果格式化字符串中包含单引号,处理方法是用2个单引号进行转义,如果是数字,则需要加上格式: MessageFormat.format("(''{0}'',''{1}'',{2,number, ...

  6. 媲美oracle awr/statspack的mysql awr第一版发布

    现发布alpha版mysql awr,其提供的特性类似于oracle awr或statspack+集中式监控.对于原来从事oracle dba或者相关运维的人原来说,这会是个不错的选择. 至于我为什么 ...

  7. Android5.0新特性——新增的Widget(Widget)

    新增的Widget RecyclerView RecyclerView是ListView的升级版,它具备了更好的性能,且更容易使用.和ListView一样,RecyclerView是用来显示大量数据的 ...

  8. [Architecture Pattern] Factory Builder

    [Architecture Pattern] Factory Builder 目的 同时提供延迟注入对象.挂载注入项目这两个功能 情景 在开发系统时,如果需要在运行时间才生成并注入对象,可以套用Fac ...

  9. swift学习笔记之-错误处理

    //错误处理 import UIKit /*错误处理(Error Handling):响应错误以及从错误中恢复的过程 在 Swift 中,错误用符合ErrorType协议的类型的值来表示.这个空协议表 ...

  10. WCF服务部署到IIS7.5

    下面介绍如何把WCF服务部署到IIS: 为WCF服务创建.svc文件 我们知道,每一个ASP.NET Web服务都具有一个.asmx文本文件,客户端通过访问.asmx文件实现对相应Web服务的调用.与 ...