【发布时间】:2018-04-06 23:53:54
【问题描述】:
我创建了一个需要可序列化的树数据结构,但每棵树都共享一个公共根对象,这是一个公共静态最终常量。
我遇到的问题如下所示。在我序列化 ROOT 对象后,反序列化会创建一个新的 Tree 对象,而不是返回对原始常量的引用。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
public class Main {
public static final class Tree implements Serializable {
public final ArrayList<Tree> branches = new ArrayList<>();
}
public static final Tree ROOT = new Tree();
public static void main(String[] args) throws Exception {
File file = new File("C:/Users/Stephen/Desktop/temp.bin");
ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file));
oout.writeObject(ROOT);
oout.writeObject(ROOT);
oout.close();
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
Tree t1 = (Tree) oin.readObject();
Tree t2 = (Tree) oin.readObject();
oin.close();
System.out.println(ROOT == t1); // false
System.out.println(t1 == t2); // true
}
}
第一个打印语句输出“false”,但我希望它是“true”。
【问题讨论】:
-
由于一些 cmets 提到了这一点:是的,我确实知道 == 和 #equals(Object) 之间的区别。我想要前者。从 ObjectInputStream 读取对象时,我希望它返回对已序列化的完全相同的公共静态最终 ROOT 对象的引用,而不是不同的 Tree 对象,即使该不同的对象#equals to ROOT。
-
进一步澄清:我理解为什么这段代码输出“假”。我有 15 年以上的 Java 开发经验,不需要关于语言基础的建议。我正在寻找解决这个问题的方法。我需要一种方法来识别现有的公共静态最终对象何时被反序列化,而不是创建一个新对象,而是返回对原始对象的引用。我的第一次尝试是编写一个自定义的反序列化方法(如此处所述:oracle.com/technetwork/articles/java/javaserial-1536170.html),但这种方法似乎会自动创建一个新对象。
-
您是否研究过 readResolve 和 writeResolve?我想他们可能会做你想做的事。 (不过,要做到正确并不是超级简单;Effective Java 有一个关于它的两个部分,iirc)
-
具体来说,我推荐看
Currency类的实现。 -
当您以简化的方式编写问题时,不会自动显示您 15 年的经验。人们会自动假设更简单的问题,因为 SO 充满了它们。您必须小心不要发生这种情况:stackoverflow.com/questions/49533897/…(它有 -2 / +2 分,因为人们误解了这个问题)。
标签: java serialization