单例设计类:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauwmc0NWL0xWYtQnZph2cvw1LcpDc0RHaiojIsJye.png)
package com.test.singleton;
import java.io.ioexception;
import java.io.objectstreamexception;
import java.io.serializable;
public class singleton implements serializable{
/**
*
*/
private static final long serialversionuid = 768457893059530646l;
private singleton(){
system.out.println("here...");
//避免反射机制,导致的多例问题,通过反射机制仍然可以对私有构造函数进行操作
if(instance != null){
return;
}
}
private static final singleton instance = new singleton();
public static singleton getinstance(){
return instance;
public void readobject(java.io.objectinputstream in) throws ioexception, classnotfoundexception{
//
* 严格单例,确保remote instance不会干扰单例模式,避免在发序列化过程中对单例的影响.
* @return
* @throws objectstreamexception
public object readresolve() throws objectstreamexception{
}
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauwmc0NWL0xWYtQnZph2cvw1LcpDc0RHaiojIsJye.png)
///////////流方式:
import java.io.file;
import java.io.fileinputstream;
import java.io.fileoutputstream;
import java.io.objectinputstream;
import java.io.objectoutputstream;
public class serializecheckmain {
* @param args
*/
public static void main(string[] args) throws exception{
// todo auto-generated method stub
singleton s1 = singleton.getinstance();
file file = new file("d:\\singletome.txt");
objectoutputstream oos = new objectoutputstream(new fileoutputstream(file));
oos.writeobject(s1);
oos.close();
objectinputstream ois = new objectinputstream(new fileinputstream(file));
singleton s2 = (singleton)ois.readobject();
system.out.println("hashcode 1 : " + s1.hashcode());
system.out.println("hashcode 2 : " + s2.hashcode());
system.out.println("equal : " + (s1 == s2));//打破单例
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauwmc0NWL0xWYtQnZph2cvw1LcpDc0RHaiojIsJye.png)
//////////////////////反射方式:
import java.lang.reflect.constructor;
/**
* @author liuguanqing
* 反射机制,测试单例
*/
public class refletcheckmain {
constructor[] constructors = singleton.class.getdeclaredconstructors();
constructor<singleton> c = constructors[0];
c.setaccessible(true);
singleton s2 = c.newinstance(null);
注意,序列化和反序列化,是java使用字节码技术生成对象,将不会执行构造器方法.
注意到在writereplace和readresolve,我们可以严格控制singleton的对象,在同一个jvm中完完全全只有唯一的对象,控制不让singleton对象产生副本.
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauwmc0NWL0xWYtQnZph2cvw1LcpDc0RHaiojIsJye.png)
package com.test.main;
public class testserializable implements serializable{
private static final long serialversionuid = -1740221592194879964l;
private integer age;
private string name;
public testserializable(){
system.out.println("contrustor..");
public integer getage() {
return age;
public void setage(integer age) {
this.age = age;
public string getname() {
return name;
public void setname(string name) {
this.name = name;
private void writeobject(java.io.objectoutputstream out) throws ioexception{
system.out.println("writeobject");
out.writeint(this.age);
out.writeint(this.name.getbytes("utf8").length);
out.write(this.name.getbytes("utf8"));
private void readobject(java.io.objectinputstream in) throws ioexception, classnotfoundexception{
this.age = in.readint();
int chars = in.readint();
byte[] bytes = new byte[chars];
in.readfully(bytes);
this.name = new string(bytes,"utf8");
system.out.println("readobject");
system.out.println("readresolve");
return this;
public object writereplace() throws objectstreamexception{
system.out.println("writereplace");
* @param args
objectoutputstream oos = new objectoutputstream(new fileoutputstream("d:\\sss.txt"));
testserializable ss = new testserializable();
ss.setage(12);
ss.setname("zhangsan");
oos.writeobject(ss);
objectinputstream ois = new objectinputstream(new fileinputstream("d:\\sss.txt"));
testserializable ss2 = (testserializable)ois.readobject();
system.out.println(ss == ss2);
system.out.println(ss2.getname());
ois.close();
//////////执行结果
//contrustor..
//writereplace
//writeobject
//readobject
//readresolve
//false
//zhangsan
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5ichR3cf52bjl2LcNXZnFWbp9CXt92YuUWelRXauwmc0NWL0xWYtQnZph2cvw1LcpDc0RHaiojIsJye.png)
//////////externalizable接口是serializable的子接口,不过此接口提供了两个特殊的扩展方法:
@override
public void writeexternal(objectoutput out) throws ioexception {
system.out.println("writeex");
out.writeint(50);
public void readexternal(objectinput in) throws ioexception,
classnotfoundexception {
system.out.println("readex");
注意实现externalizable接口的类,在发序列化时,将会执行构造函数,因为对于流操作而言,此对象是有明确类型的(serializable接口是个标记接口).
而且,如果实现了writeexternal和readexternal,将不会在执行readobject和writeobject,因为此时这两个方法已经被"擦除".
对于java序列化和反序列化,被序列化的类中有关于serialversionuid会带来一些问题;
1) 如果你调整了class结构(比如新增/去除某个属性值,但是不能引入编译错误),但没有修改serialversionuid;那么在反序列化和序列化时不会带来异常,只是可能导致部分属性在get时为null.
2) 如果你调整了class结构,同时也修改了serialversionuid;如果序列化和反序列双方没有保持uid一致的话,将会直接导致反序列化异常.(java.io.invalidclassexception)
3) 如果你没有显式的声明serialversionuid,那么对于jvm而言,不同的class类结构(属性列表和方法列表)将会得出不同的uid;因此如果序列化双方不能保持一致的uid,仍然会带来问题.
原文链接:[http://wely.iteye.com/blog/2228826]