title: Implementing an equivalent to String.intern() for other objects
body: <p>I'm trying to implement an equivalent to String.intern(), but for other objets.
  My goal is the following:
  I've an object A which I will serialize and then deserialize.
  If there is another reference to A somewhere, I want the result of the deserialization to be the same reference. </p>
  
  <p>Here is one example of what I would expect.</p>
  
  <pre><code>MyObject A = new MyObject();
  A.data1 = 1;
  A.data2 = 2;
  byte[] serialized = serialize(A);
  A.data1 = 3;
  MyObject B = deserialize(serialized); // B!=A and B.data1=1, B.data2=2
  MyObject C = B.intern(); // Here we should have C == A. Consequently C.data1=3 AND C.data2=2
  </code></pre>
  
  <p>Here is my implementation atm. (the <code>MyObject</code> class extends <code>InternableObject</code>)</p>
  
  <pre><code>public abstract class InternableObject {
  
  private static final AtomicLong maxObjectId = new AtomicLong();
  private static final Map&lt;Long, InternableObject&gt; dataMap = new ConcurrentHashMap&lt;&gt;();
  private final long objectId;
  
  public InternableObject() {
      this.objectId = maxObjectId.incrementAndGet();
  
      dataMap.put(this.objectId, this);
  }
  
  @Override
  protected void finalize() throws Throwable {
      super.finalize();
      dataMap.remove(this.objectId);
  }
  
  public final InternableObject intern() {
      return intern(this);
  }
  
  public static InternableObject intern(InternableObject o) {
      InternableObject r = dataMap.get(o.objectId);
  
      if (r == null) {
          throw new IllegalStateException();
      } else {
          return r;
      }
  }
  }
  </code></pre>
  
  <p>My unit test (which fails): </p>
  
  <pre><code>    private static class MyData extends InternableObject implements Serializable {
  
      public int data;
  
      public MyData(int data) {
          this.data = data;
      }
  }
  
  @Test
  public void testIntern() throws Exception {
      MyData data1 = new MyData(7);
  
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(data1);
      oos.flush();
      baos.flush();
      oos.close();
      baos.close();
      ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
      ObjectInputStream ois = new ObjectInputStream(bais);
      MyData data2 = (MyData) ois.readObject();
  
      Assert.assertTrue(data1 == data2.intern()); // Fails here
  }
  </code></pre>
  
  <p>The failure is due to the fact that, when deserializing, the constructor of InternableObject is called, and thus objectId will be 2 (even if the serialized data contains "1")</p>
  
  <p>Any idea about how to solve this particular problem or, another approach to handle the high level problem ?</p>
  
  <p>Thanks guys</p>