当前位置:首页 > 开发 > 编程语言 > Java > 正文

java enum实现的单例

发表于: 2012-03-15   作者:837062099   来源:转载   浏览:
摘要: 为了防止通过反序列化得到多个对象,EJ提倡使用enum实现单例: 关于枚举的对象为什么可以反序列化:可以看Enum类的如下方法: /** * prevent default deserialization */ private void readObject(ObjectInputStream in) throws IOException,
为了防止通过反序列化得到多个对象,EJ提倡使用enum实现单例:
关于枚举的对象为什么可以反序列化:可以看Enum类的如下方法:
 /**
      * prevent default deserialization
      */
    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");
    }

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Test {
	public static void main(String[] args) throws Exception {
		Singleton d1 = Singleton.INSTANCE;
		d1.setName("a fucker.");
		System.out.println(d1);
		
		FileOutputStream fos = new FileOutputStream("out.data");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(d1);
		fos.close();
		oos.close();
		
		FileInputStream fis = new FileInputStream("out.data");
		ObjectInputStream ois = new ObjectInputStream(fis);
		Object o = ois.readObject();
		fis.close();
		ois.close();
		
		Singleton d2 = (Singleton)o;
		
		System.out.println(d2);
		System.out.println(d1 == d2);
	}
}
enum Singleton implements Serializable {
	
	INSTANCE;
	
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "[" + name + "]";
	}
}

因为一个enum常量(这里是INSTANCE)代表了一个enum的实例,enum类型只能有这些常量实例。标准保证enum常量(INSTANCE)不能被克隆,也不会因为反序列化产生不同的实例,想通过反射机制得到一个enum类型的实例也不行的。


如果用一般方式写单例模式,该单例类如果实现了Serializable接口,则必须添加readResolve()方法,当然我认为按照Enum类的设计在 readObject(ObjectInputStream in)中抛出异常也可以有效防止反序列化:
public class Singleton {
	
	private static volatile Singleton st;

	private Singleton(){};
	
	public static Singleton getInstance() {
		if (null == st) {
			synchronized (Singleton.class) {
				if (st == null) {
					st = new Singleton();
					return st;
				}
			}
		}
		return st;
	}

	/**
	 * 反序列化时内存Hook这段代码
	 * @return
	 */
	private Object readResolve() {
		return st;
	}
}


 ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
 ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;

这两个方法可以理解为序列化和反序列化过程的入口和出口。writeReplace()返回的对象,就是要被序列化的对象,我们有机会在序列化前把这个对象给换成我们确定好的那个(如果不是“故意捣乱”,暂时没想到有什么用);而readResolve()方法就是在反序列化完成得到对象前,把这个对象给换成我们确定好的那个。

明白了吧?为了防止有人恶意通过序列化的机制破坏定义好的单例,我们就需要自己实现readResolve()方法,把单例定义的唯一实现在这个方法中返回。
一般单例处理方法: http://www.blogjava.net/dreamstone/archive/2006/11/04/79026.html
恶汉式的单例也有问题: http://www.ibm.com/developerworks/cn/java/j-lo-clobj-init/index.html

java enum实现的单例

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
static, enum, 内部类与单例模式 标签: Java与设计模式 Java static与初始化块拾忆 static关键字的
单例模式的本质是在运行过程中,某个类只能实例化一个对象;下面是单例模式最基本的实现方式 packag
单例模式(Singleton):当系统中只需要的某个类的唯一对象时,可以使用该模式。 为什么会用到该模
单例设计模式-------懒汉式,饿汉式 单例设计模式是一种很常见的设计模式 在这里介绍两种单例设计模
基本概念 Singleton 是一种创建性模型,它用来确保只产生一个实例,并提供一个访问它的全局访问点.对
一.饿汉模式(类加载的时候就会实例化,线程安全) 1 package com.sun.singleton; 2 3 //饿汉模式 4
一.饿汉模式(类加载的时候就会实例化,线程安全) 1 package com.sun.singleton; 2 3 //饿汉模式 4
文章出自:http://blog.csdn.net/zhengzhb/article/details/7331369 定义:确保一个类只有一个实例
public class SingleInstance { private String name; public String getName() { return name; } p
这种设计模式是保证类只有一个类Class只有一个实例存在,如果再次新建这个类,之前的类会立即被摧毁
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号