代码之家  ›  专栏  ›  技术社区  ›  Konrad Rudolph

序列化是否保留了对象标识?

  •  26
  • Konrad Rudolph  · 技术社区  · 16 年前

    Serializable 接口和 ObjectOutputStream

    我的API依赖于对象标识来执行某些操作,我想知道它是否会通过序列化来保留。也就是说: a b a == b 在序列化之前,反序列化之后它仍然成立吗?

    我发现了一些短信 claim the contrary 但他们要么写的是JRE的旧版本(我只对1.6和1.5感兴趣),要么关心RMI(这与我无关)。

    documentation technical article 在sun.com上提到 对象输出流

    Ive尝试过(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);
        }
    }
    
    2 回复  |  直到 16 年前
        1
  •  18
  •   ChssPly76    16 年前

    对于两个任意对象a和b,如果它在序列化之前保持a==b,那么在反序列化之后它仍然保持true:

    1. a和b都作为同一流的一部分写入并随后从中读取。以下是引用自 ObjectInputStream 文档:“使用 参考共享 机制。"
    2. a和b类不覆盖 readResolve() 这有可能改变恢复引用的方式;持有a和b的班级同样如此。

    对于所有其他情况,对象标识将不会被保留。

        2
  •  10
  •   ocirocir    12 年前

    答案是 be==。

    然而,在“单序列化”中,例如单个客户端-服务器消息,它是一个多次包含同一对象的图,然后在反序列化时,标识 保存。

    但是,对于第一种情况,您可以提供 readResolve 类型安全枚举 图案)。 readResolve 是一个私有方法,JVM将在反序列化的Java对象上调用它,使对象有机会返回不同的实例。例如,这就是 TimeUnit enum 枚举 的已添加到语言中:

    public class TimeUnit extends Serializable {
    
        private int id;
        public TimeUnit(int i) { id = i; }
        public static TimeUnit SECONDS = new TimeUnit(0);
    
        //Implement method and return the relevant static Instance
        private Object readResolve() throws ObjectStreamException {
            if (id == 0) return SECONDS;
            else return this;
        }
    }
    

    .

    推荐文章