序列化是否保留对象身份?
我使用 Java Serialized
接口和 ObjectOutputStream
来序列化对象(到目前为止,此方法已经足以满足我的目的)。
我的 API 依赖于对象标识来执行某些操作,我想知道它是否会通过序列化来保留。也就是说:如果对于任意两个对象a
和b
,在序列化之前它持有a == b
,那么反序列化后仍然保留?
我发现一些文本 声明相反 – 但他们要么写了旧版本的 JRE(我只对 1.6 或许 1.5 感兴趣),要么关心 RMI(这与我无关) 。
关于对象的 文档 并不是很及时身份。 sun.com 上的一篇技术文章提到了 ObjectOutputStream
对对象使用缓存,对我来说,只有当对象身份确实被保留时才有意义,但我没有足够的信心依赖这个脆弱的证据。
我已经尝试过(Java 1.6,OS X)并发现是的,对象的标识通过序列化保持不变。但我可以从这些结果中推断还是它们不可靠?
对于我的测试,我序列化了以下对象图:
C----------+
| b1 b2 |
+----------+
| |
v v
B---+ B---+
| a | | a |
+---+ +---+
\ /
\ /
\/
A----+
| |
+----+
最小的复制代码:
import java.io.*;
public class SerializeTest {
static class A implements Serializable {}
static class B implements Serializable {
final A a;
public B(A a) {
this.a = a;
}
}
static class C implements Serializable {
final B b1, b2;
public C() {
A object = new A();
b1 = b2 = new B(object);
}
}
public static void main(String[] args) throws IOException,
ClassNotFoundException {
C before = new C();
System.out.print("Before: ");
System.out.println(before.b1.a == before.b2.a);
// Serialization.
ByteArrayOutputStream data = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(data);
out.writeObject(before);
out.close();
// Deserialization.
ObjectInputStream in =
new ObjectInputStream(new ByteArrayInputStream(data.toByteArray()));
C after = (C) in.readObject();
System.out.print("After: ");
System.out.println(after.b1.a == after.b2.a);
}
}
I am using the Java Serializable
interface and the ObjectOutputStream
to serialize objects (until now, this method has been sufficient for my purposes).
My API relies on object identity for some operations and I’m wondering if it will be preserved by serialization. That is to say: if, for two arbitrary objects a
and b
, it holds a == b
before serialization, does it still hold after deserialization?
I’ve found some texts that claim the contrary – but they either wrote about an older version of the JRE (I’m only interested in 1.6 and perhaps 1.5), or were concerned with RMI (which is not relevant for me).
The documentation isn’t very forthcoming regarding object identity. A technical article on sun.com mentions that ObjectOutputStream
uses caching on objects, which to me only makes sense if the object identity is indeed preserved but I’m not confident enough to rely on this flimsy evidence.
I’ve tried it out (Java 1.6, OS X) and found that yes, the identity of objects remains unchanged by serialization. But can I extrapolate from these results or are they unreliable?
For my test, I’ve serialized the following object graph:
C----------+
| b1 b2 |
+----------+
| |
v v
B---+ B---+
| a | | a |
+---+ +---+
\ /
\ /
\/
A----+
| |
+----+
A minimal reproducing code:
import java.io.*;
public class SerializeTest {
static class A implements Serializable {}
static class B implements Serializable {
final A a;
public B(A a) {
this.a = a;
}
}
static class C implements Serializable {
final B b1, b2;
public C() {
A object = new A();
b1 = b2 = new B(object);
}
}
public static void main(String[] args) throws IOException,
ClassNotFoundException {
C before = new C();
System.out.print("Before: ");
System.out.println(before.b1.a == before.b2.a);
// Serialization.
ByteArrayOutputStream data = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(data);
out.writeObject(before);
out.close();
// Deserialization.
ObjectInputStream in =
new ObjectInputStream(new ByteArrayInputStream(data.toByteArray()));
C after = (C) in.readObject();
System.out.print("After: ");
System.out.println(after.b1.a == after.b2.a);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于两个任意对象 a 和 b,如果在序列化之前它保持 a == b,则在反序列化之后它仍然保持 true IF:
readResolve()
;持有 a 和 b 的类也不会。对于所有其他情况,将不会保留对象标识。
For two arbitrary objects a and b, if it holds a == b before serialization, it will still hold true after deserialization IF:
readResolve()
that has the potential of changing how references are restored back; neither do classes that hold a and b.For all other cases, object identity will NOT be preserved.
答案是否,默认情况下,如果您正在考虑对给定对象/图进行 2 个单独的序列化,则不会通过序列化保留对象标识。例如,如果我通过线路序列化一个对象(也许我通过 RMI 将其从客户端发送到服务器),然后再次执行此操作(在单独的 RMI 调用中),那么服务器上的 2 个反序列化对象将不是是==。
然而,在“单序列化”中,例如单个客户端-服务器消息,它是多次包含相同对象的图形,然后在反序列化时,身份将被保留。
但是,对于第一种情况,您可以提供
readResolve
方法,以确保返回正确的实例(例如,在类型安全枚举模式中)。 readResolve 是一个私有方法,JVM 将在反序列化的 Java 对象上调用该方法,使该对象有机会返回不同的实例。例如,这就是在将enum
添加到语言之前TimeUnit
enum
的实现方式:。
The answer is no, by default object identity is not preserved via serialization if you are considering 2 separate serializations of a given object/graph. For example, if a I serialize an object over the wire (perhaps I send it from a client to a server via RMI), and then do it again (in separate RMI calls), then the 2 deserialized objects on the server will not be ==.
However, in a "single serialization" e.g. a single client-server message which is a graph containing the same object multiple times then upon deserialization, identity is preserved.
For the first case, you can, however, provide an implementation of the
readResolve
method in order to ensure that the correct instance is returned (e.g. in the typesafe enum pattern).readResolve
is a private method which will be called by the JVM on a de-serialized Java object, giving the object the chance to return a different instance. For example, this is how theTimeUnit
enum
may have been implemented beforeenum
's were added to the language:.