类加载机制 - java单例饿汉模式对象创建时间点疑问
阿神
阿神 2017-04-18 10:56:01
0
1
719

关于java单例中饿汉式模式的解释,大多如下:
饿汉模式线程安全的,在类创建的同时就已经创建好一个静态的对象,相对与懒汉模式对象创建过早,浪费空间。

但是jvm中明确定义是:虚拟机规范则是严格规定了有且只有5种情况必须立即对类进行“初始化”

1)遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。
2)使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
3)当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
4)当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。
5)当使用JDK 1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_get-Static、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。

public class Singleton {

private static Singleton instance = new Singleton();  
private Singleton (){}  
public static Singleton getInstance() {  
return instance;  
}  

}

根据第1)条可知道,只有调用单例模式的getInstance的时候,才会初始化instance字段。

写了个例子来验证这点:

public class SingletonTest {

private static SingletonTest singleton=new SingletonTest();
private SingletonTest(){
    System.out.println("new signleton");
}
public static SingletonTest getSingleton(){
    return singleton;
}

}

public class Test {

public static void main(String args[]){
    SingletonTest singleton=null;
    System.out.println(singleton);
    singleton= SingletonTest.getSingleton();
}

}

执行main方法后的结果是:

null

new signleton

上面的例子可以看出,在调用getInstance方法的时候,jvm才会对SingletonTest类初始化。

问题:在不使用反射模式加载单例类的情况下,懒汉模式和饿汉模式有区别吗?

阿神
阿神

闭关修行中......

reply all(1)
巴扎黑

A .net programmer.
You add a static field to the SingletonTest class, do not call getSingleton, call this field directly, and see what is output.

Also don’t memorize the three modes of the singleton mode. You must understand them and then you can flexibly use these three modes.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template