序列化相关文章:
Java 序列化 之 SerializableJava 序列化之 Externalizable
当我们使用Singleton模式时,应该是期望某个类的实例应该是唯一的,但如果该类是可序列化的,那么发序列化后还会是单例的吗?下面我们通过如下示例一来验证一下:
示例一
User 类
User 类是单例模式,使用的饿汉模式,在类加载的时候就创建对象实例。
public class User implements Serializable { private static final long serialVersionUID = 3380014540967816490L; private String userName; private String password; private static User user = new User(''zhangsan'', ''test''); private User(String userName, String password) { this.userName = userName; this.password = password; } public static User getInstance() { return user; } public String getUserName() { return userName; } public String getPassword() { return password; }
小编是一个有着5年工作经验的java程序员,对于java,自己有做资料的整合,一个完整学习java的路线,学习资料和工具,相信这里有很多学习java的小伙伴,我创立了一个2000人学习扣群,479121291。每晚都有java的直播课程。无论是初级还是进阶的小伙伴小编我都欢迎!
Test 类
测试类,把 User 的单例实例序列化后在反序列化。
public class Test{ public static void main(String[] args) throws Exception { File file = new File(''d:\\a.user''); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject(User.getInstance()); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); User user = (User) ois.readObject(); System.out.println(user); if(user==User.getInstance()){ System.out.println(''同一个实例''); }else{ System.out.println(''不同的实例''); } }}
执行结果如下:
输出的结果:User [userName=zhangsan, password=123456]不同的实例
通过结果可以看出,单例模式的饿汉模式也无法确保对象实例是单例的。
那么我们应该怎么解决这个问题呢?
readResolve() 方法
public class User implements Serializable { private static final long serialVersionUID = 3380014540967816490L; private String userName; private String password; private static User user = new User(''zhangsan'', ''123456''); private User(String userName, String password) { this.userName = userName; this.password = password; } public static User getInstance() { return user; } public String getUserName() { return userName; } public String getPassword() { return password; } public Object readResolve(){ return getInstance(); } @Override public String toString() { return ''User [userName='' + userName + '', password='' + password + '']''; }}
我们在 User 类中添加了一个 readResolve() 方法,该方法直接返回单例中的示例。然后在执行 Test.main() 方法执行结果如下:
输出的结果:User [userName=zhangsan, password=123456]不同的实例
无论是实现Serializable接口,或是Externalizable接口,当从I/O流中读取对象时,readResolve()方法都会被调用到。实际上就是用readResolve()中返回的对象直接替换在反序列化过程中创建的对象。