`
coolxing
  • 浏览: 873882 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
9a45b66b-c585-3a35-8680-2e466b75e3f8
Java Concurre...
浏览量:97186
社区版块
存档分类
最新评论

实现严谨的singleton类

阅读更多

[coolxing按: 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正.] 

singleton模式是大多数javaer耳熟能详的, 不过要做到真正的单例其实很不容易, 你需要考虑以下问题:

1. 延迟加载时多线程环境下是否能保证单例?

2. 是否可以通过暴力反射获得新的对象?

3. 是否可以通过clone方法获得新的对象?

4. 是否可以通过序列化获得新的对象?

 

对于问题1, 可以通过双重检查加锁解决. 这是运用单例的常识, 不再详细说明.

问题2, 3, 4则是很难避免的.

但是我们可以通过java提供的一种简单的方式创建一个真正的singleton类: 仅有一个实例的枚举类型. 如:

 

public enum Weekday {
	MONDAY;
	private Weekday() {}
}

 

下面我们对这个枚举类进行一一验证.

 

暴力反射

测试代码如下:

public static void main(String[] args) throws Exception {
		Class<?> clazz = Weekday.class;
		Constructor<?> cc = clazz.getDeclaredConstructor(null);
		cc.setAccessible(true);
		cc.newInstance(null);
}

 

运行结果是抛出异常:Exception in thread "main" java.lang.NoSuchMethodException: cn.xing.test.Weekday.<init>()

明明Weekday有一个无参的构造函数, 为何不能通过暴力反射访问?

最新的Java Language Specification (§8.9)规定:  Reflective instantiation of enum types is prohibited. 这是java语言的内置规范.

 

 

clone方法

所有的枚举类都继承自java.lang.Enum类, 而不是Object类. 在java.lang.Enum类中clone方法如下:

protected final Object clone() throws CloneNotSupportedException {
	throw new CloneNotSupportedException();
}

 

调用该方法将抛出异常, 且final意味着子类不能重写clone方法, 所以通过clone方法获取新的对象是不可取的.

 

序列化

java.lang.Enum类的readObject方法如下:

private void readObject(ObjectInputStream in) throws IOException,
        ClassNotFoundException {
            throw new InvalidObjectException("can't deserialize enum");
}

private void readObjectNoData() throws ObjectStreamException {
        throw new InvalidObjectException("can't deserialize enum");
}
 

同暴力反射一样, Java Language Specification (§8.9)有着这样的规定: the special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization.

 

综上所述, 创建仅有一个实例的枚举类型是实现singleton的最简单, 最严谨的方式.

Java Language Specification下载路径:http://docs.oracle.com/javase/specs/

 

分享到:
评论
1 楼 heipacker 2013-10-06  
这个不错!

相关推荐

    Actionscript 3.0 类关系图PDF格式

    10. **编程模式**:类关系图可能还涵盖了设计模式,如单例模式(Singleton)、工厂模式(Factory)等,这些模式在ActionScript 3.0 开发中广泛应用。 通过这个PDF,开发者可以更清晰地理解ActionScript 3.0 类之间...

    typescript-node-singleton:关于如何使用 Typescript 实现单例 node.js 模块的示例

    TypeScript 提供了更严谨的类型检查,使得在实现单例时能更好地避免潜在错误。 以下是一个简单的 TypeScript 单例模式实现: ```typescript // singleton.ts class Singleton { private static instance: ...

    Python中实现单例模式的n种方式和原理

    然而,全局变量的方法难以管理且容易造成状态不一致的问题,因此在实际开发中往往需要更严谨的实现方式。 其次,使用metaclass是另一种常见的单例实现方式。在Python中,metaclass是创建类对象的“类”。当定义一个...

    atm.rar_it

    8. **设计模式**:在实现ATM系统时,可能会用到如单例模式(Singleton)来确保只有一个ATM实例,工厂模式(Factory)来创建不同类型的账户,策略模式(Strategy)来实现不同的交易策略。 9. **用户认证**:为了安全...

    C++课程设计大作业

    10. **设计模式**:高级的课程设计可能需要应用设计模式,如单例模式(Singleton)用于管理通讯录实例,工厂模式(Factory)用于创建联系人对象,或者策略模式(Strategy)用于实现不同的搜索策略。 在完成这个大...

    Discuz!_X2笔记.pdf

    #### 单例模式(Singleton Pattern) **概述** 单例模式是一种常用的软件设计模式,在整个系统中只存在一个实例对象,可以确保系统环境中某个类只有一个实例存在,并且提供一个全局访问点。在Discuz! X2中,单例模式...

    Data Structures And Algorithms With Object-Oriented Design Patterns In C Sharp.pdf

    这些设计模式包括单例(Singleton)、容器(Container)、枚举(Enumeration)、适配器(Adapter)以及访问者(Visitor)。书中通过具体的实例展示了如何运用这些模式来创建优秀的软件设计。 #### 二、面向对象设计...

    ts-design-patterns:使用Typescript编写和解释的设计模式

    1. **单例模式(Singleton)**:确保一个类只有一个实例,并提供一个全局访问点。在TypeScript中,可以使用模块和静态属性来实现单例,保证在整个应用程序中只有一个实例存在。 2. **工厂模式(Factory)**:提供一...

    reversi:AI 黑白棋,它必须连接到服务器

    Java提供了Thread类和Runnable接口来实现并发执行,确保游戏流程的流畅性。 4. **图形用户界面(GUI)**:为了提供用户友好的交互,游戏可能使用Java Swing或JavaFX库创建GUI。Swing是Java的标准GUI工具包,可以...

    fullHouseToernooiLeider:全屋锦标赛领袖计划

    1. **面向对象编程**:Java的核心是面向对象编程(OOP),项目可能会定义多个类来代表不同的实体,如锦标赛(Tournament)、选手(Player)、比赛(Match)等,通过封装、继承和多态等机制实现模块化和可扩展性。...

    DZ.SodaMachine_Project

    【DZ.SodaMachine_Project】是一个基于C#编程语言的项目,主要涉及的是模拟自动售货机(SodaMachine)的实现。在这个项目中,我们可以深入学习和理解C#的基础语法、面向对象编程以及控制台应用程序开发的相关知识。 ...

Global site tag (gtag.js) - Google Analytics