下面显示的是单例对象的创建。
public class Map_en_US extends mapTree {
private static Map_en_US m_instance;
private Map_en_US() {}
static{
m_instance = new Map_en_US();
m_instance.init();
}
public static Map_en_US getInstance(){
return m_instance;
}
@Override
protected void init() {
//some code;
}
}
我的问题是使用静态块进行实例化的原因是什么。我熟悉单身实例化的以下形式。
public static Map_en_US getInstance(){
if(m_instance==null)
m_instance = new Map_en_US();
}
答案 0 :(得分:36)
答案 1 :(得分:1)
如果在getInstance()
方法中初始化,则可以获得竞争条件,即如果2个线程同时执行if(m_instance == null)
检查,则两者都可能看到实例为空,因此两者都可能调用{{ 1}}
由于静态初始化程序块只执行一次(由一个执行类加载器的线程执行),因此你没有问题。
答案 2 :(得分:1)
这种消除静态块的方法如何:
private static Map_en_US s_instance = new Map_en_US() {{init();}};
它做同样的事情,但是更整洁。
此语法的说明:
外部括号组创建一个匿名类
内部支撑组称为“实例块” - 它在构造过程中会发生爆炸
这种语法通常被错误地称为“双括号初始化器”语法,通常是那些不了解发生了什么的人。
另外,请注意:
m_
是 instance (即成员)字段的命名约定前缀
s_
是 class (即静态)字段的命名约定前缀
所以我将字段的名称更改为s_...
。
答案 3 :(得分:0)
这取决于init方法的资源密集程度。如果它,例如做了很多工作,也许你希望在应用程序启动时完成工作而不是第一次调用。也许它从互联网下载地图?我不知道......
答案 4 :(得分:0)
当JVM首次加载类时,将执行静态块。正如Bruno所说,这对线程安全有帮助,因为两个线程不可能第一次在同一个getInstance()调用上进行争用。
答案 5 :(得分:0)
thread-safe
,因为除了返回实例之外,你没有在方法中做任何事情。答案 6 :(得分:0)
静态块实例化您的类并且只调用一次默认的构造函数(如果有的话)以及应用程序启动时所有静态元素都由JVM加载。
使用getInstance()方法,在调用方法时构建并初始化类的对象,而不是静态初始化。如果你同时在不同的线程中运行getInstance(),那就不安全了。
答案 7 :(得分:0)
静态块在此处允许init
调用。其他编码方式可能就像这样(喜欢的是品味问题)
public class Map_en_US extends mapTree {
private static
/* thread safe without final,
see VM spec 2nd ed 2.17.15 */
Map_en_US m_instance = createAndInit();
private Map_en_US() {}
public static Map_en_US getInstance(){
return m_instance;
}
@Override
protected void init() {
//some code;
}
private static Map_en_US createAndInit() {
final Map_en_US tmp = new Map_en_US();
tmp.init();
return tmp;
}
}
更新已修正每VM spec 2.17.5,评论中的详细信息
答案 8 :(得分:0)
// Best way to implement the singleton class in java
package com.vsspl.test1;
class STest {
private static STest ob= null;
private STest(){
System.out.println("private constructor");
}
public static STest create(){
if(ob==null)
ob = new STest();
return ob;
}
public Object clone(){
STest obb = create();
return obb;
}
}
public class SingletonTest {
public static void main(String[] args) {
STest ob1 = STest.create();
STest ob2 = STest.create();
STest ob3 = STest.create();
System.out.println("obj1 " + ob1.hashCode());
System.out.println("obj2 " + ob2.hashCode());
System.out.println("obj3 " + ob3.hashCode());
STest ob4 = (STest) ob3.clone();
STest ob5 = (STest) ob2.clone();
System.out.println("obj4 " + ob4.hashCode());
System.out.println("obj5 " + ob5.hashCode());
}
}
-------------------------------- OUT PUT -------------------------------------
private constructor
obj1 1169863946
obj2 1169863946
obj3 1169863946
obj4 1169863946
obj5 1169863946
答案 9 :(得分:-1)
synchronized getInstance()
方法声明处理)