在CJC(一)
中提到一个问题,即 readResolve方法是干啥的? 当时也没多想, 只是列在那里, 今天忙里偷闲地把搜点材料整理下这个问题.
原来这个方法跟对象的序列化相关(这样倒是解释了为什么 readResolve方法是private修饰的). ??? 怎么跟对象的序列化相关了?
下面我们先简要地回顾下对象的序列化. 一般来说, 一个类实现了
Serializable接口, 我们就可以把它往内存地写再从内存里读出而"组装"成一个跟原来一模一样的对象.
不过当序列化遇到单例时,这里边就有了个问题: 从内存读出而组装的对象破坏了单例的规则. 单例是要求一个JVM中只有一个类对象的, 而现在通过反序列化,一个新的对象克隆了出来.
如下例所示:
public final class MySingleton implements Serializable {
private MySingleton() { }
private static final MySingleton INSTANCE = new MySingleton();
public static MySingleton getInstance() { return INSTANCE; }
}
当把
MySingleton对象(通过getInstance方法获得的那个单例对象)序列化后再从内存中读出时, 就有一个全新但跟原来一样的MySingleton对象存在了. 那怎么来维护单例模式呢?这就要用到readResolve方法了. 如下所示:
public final class MySingleton implements Serializable{
private MySingleton() { }
private static final MySingleton INSTANCE = new MySingleton();
public static MySingleton getInstance() { return INSTANCE; }
private Object readResolve() throws ObjectStreamException {
// instead of the object we're on,
// return the class variable INSTANCE
return INSTANCE;
}
}
这样当JVM从内存中反序列化地"组装"一个新对象时,就会自动调用这个
readResolve方法来返回我们指定好的对象了, 单例规则也就得到了保证.
---------------------------------
上面用的例子来源于这个链接:http://www.javalobby.org/java/forums/t17491.html, 另这个链接中还有一个更为高级的例子, 如有兴趣可去一看.
分享到:
相关推荐
序列化与反序列化是计算机科学中的重要概念,特别是在数据存储、网络通信和持久化对象等领域。简单来说,序列化是将对象的状态转换为可存储或传输的数据格式的过程,而反序列化则是将这种数据格式恢复为原来的对象...
`readResolve()`方法通常用于解决反序列化时可能产生的副作用,如在反序列化过程中创建不必要的新对象,或者为了确保反序列化的对象与原始对象具有相同的逻辑状态。此外,这个方法也可以用于优化,比如返回一个已经...
`readResolve`方法允许开发者替换已经反序列化的对象。这在需要替换对象引用或更改其状态时非常有用。 #### 四、类描述符 **4.1 `ObjectStreamClass`类** `ObjectStreamClass`类提供了关于可序列化类的信息。它...
`readResolve()` 和 `writeReplace()` 是两个特殊的方法,可以用来自定义序列化和反序列化的行为。`readResolve()` 在反序列化时被调用,可以返回替换对象;`writeReplace()` 在序列化时被调用,可以返回一个代理...
1. **什么是序列化:** 序列化是将对象转换为字节序列的过程,这个字节序列可以被保存到磁盘、发送到网络或者通过其他方式保存和传递。序列化的目的是为了能够恢复对象,即使在不同的时间或不同的环境中也能做到这...
- `readResolve()`: 在反序列化期间,此方法允许替换返回的对象。这可以用于控制实例化逻辑,例如实现单例模式。 - `writeReplace()`: 在序列化期间,此方法允许替换要写入的对象。这通常用于优化或处理特殊类型的...
这个接口没有定义任何方法,仅仅作为一个标记,表明该类及其所有子类都支持序列化。需要注意的是,实现序列化的类应该谨慎处理其内部状态,因为序列化会保存对象的所有字段,包括私有(private)和受保护的...
`writeReplace`方法允许在序列化前替换对象,`readResolve`方法则允许在反序列化后替换对象。 5. 总结 对象序列化是Java中一种重要的功能,它使得对象的状态能够被持久化或者在网络中传输。虽然Java提供了一套默认...
为了防止恶意反序列化,可以使用`readResolve()`或`writeReplace()`方法进行替换操作。 **六、序列化策略** 1. **默认序列化**:简单地实现Serializable接口,无需额外代码,适合字段较少且不关心序列化细节的场景...
为了解决这个问题,可以在类中添加一个`readResolve()`方法,该方法会在反序列化过程中被调用,用于返回正确的单例实例。 #### 同引用实例化问题 在序列化过程中,如果两个对象引用同一个对象实例,则在反序列化时...
在反序列化过程中,有时需要验证对象的完整性,这可以通过`ObjectInputValidation`接口实现,注册验证器并在反序列化时执行验证方法。 总结来说,Java对象的生命周期涉及类加载、初始化,以及对象的创建、克隆、...
8. JSON与XML序列化:对比Java序列化与其他数据交换格式(如JSON、XML)的优缺点。 通过这个源代码,你可以学习到如何在实际项目中应用Java序列化,以及如何解决相关问题。这些实践性的例子将帮助你加深对这一重要...
为了防止恶意代码利用,Java提供了`writeReplace()`和`readResolve()`方法,允许对象在序列化和反序列化时替换自身,以增强安全性。 5. **类版本控制**:`ObjectStreamClass`维护了每个类的序列化版本ID...
- 使用`writeReplace()`和`readResolve()`方法可以控制序列化和反序列化过程。 - 使用`Externalizable`接口代替`Serializable`,可以自定义序列化和反序列化逻辑。 总之,Java对象的存储与读取是通过序列化和反...
Java 提供了 `ObjectInputStream` 类来实现反序列化: ```java try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("serializedFile.ser"))) { MyClass obj = (MyClass) ois.readObject(); ...
空间开销(序列化大小)、时间开销(序列化/反序列化时间) 序列化协议: stream、xml、json、thrift、protobuf 序列化实现: java-built-in、hessian、fastjson、jackson、gson、Thrift、ProtoBuf NIO IO: 单向、阻塞、流...
最后,`readResolve`和`writeReplace`方法可以用来控制序列化过程中替换的对象,这对于实现单例模式或其他高级用例非常有用。 总结来说,Java对象的存储与读取涉及到对象序列化和反序列化,通过实现`Serializable`...
3. 如果必须使用Java序列化,考虑实现`readResolve()`或`readObject()`方法来控制反序列化过程,确保不会执行未授权的代码。 4. 更新依赖库,确保使用的是已修复漏洞的新版本。 总结起来,Java反序列化漏洞是一个...
`readResolve()`方法会在反序列化时调用,返回的是单例的唯一实例,从而保证了单例的正确性。 总结起来,Java单例模式有多种实现方式,每种都有其适用场景。饿汉单例适用于对性能敏感且对延迟初始化无要求的情况;...