【发布时间】:2017-01-11 09:16:26
【问题描述】:
按照this answer 的建议,我正在使用序列化深度克隆一个大型 Java 类。在相应的问题中,我解释了为什么我需要以这种方式进行克隆,这突出了不同深度克隆技术结果的重要差异,即在克隆中保留共享引用,在我的情况下这是必须的。简而言之,如果在原始的两个字段中指向同一个对象,那么在深度克隆中,这些字段不应该指向两个不同的新对象,而是指向同一个新对象。通过序列化的深度克隆实现了这一点。
由于该技术需要对树中类的唯一更改是让所有类都实现Serializable,因此我不会在树的每个类中编写“克隆”方法。所以我不是在每个类中编写代码来克隆它的每个字段。但我仍然想排除克隆过程中的一些字段,为此我将transient 修饰符添加到我不想克隆的字段的声明中。这些字段在克隆中将是 null。
现在我有不同的需求。我需要能够说确实必须克隆某个字段,但不能深度克隆:只需复制引用即可;让克隆中的该字段指向与原始对象相同的对象。
所以我想知道如何使序列化通过简单地复制引用而不是序列化来克隆该特定字段 - 像对其他字段一样反序列化它。这是我的问题。
否则我能想到的唯一解决方案是在树的每个类中实现一个“克隆”方法(不一定Object.clone()),并在每个“克隆”方法中显式分配每个字段,对某些字段使用序列化并复制其他字段的参考。但是除了由于要克隆的类有很多字段而导致的大量工作之外,我还担心这样我将不再保留主对象树中的共享引用,因为我会分别克隆每个字段,因此如果树中的两个字段指向同一个对象,则在克隆每个字段时将不知道这一事实,因此序列化不可能使它们指向同一个新对象。
【问题讨论】:
-
一个想法是声明该字段瞬态,然后通过序列化克隆后复制引用。另外我相信枚举的序列化考虑到每个只能有一个实例,所以如果你可以让该字段引用的类型是枚举?
-
@OleV.V.如果我理解正确,我仍然会创建整个根对象的深层克隆,但随后将它的一些
transient字段重新分配给与原始对象相同的引用。一个问题是某些字段可能不是public或没有设置器。我不想深度克隆某些字段的另一个原因是它们是我不需要深度克隆的大型列表,因此我想将它们从深度克隆中排除以提高性能。Enum点很有趣,我可以创建一些字段Enum,但对于其他一些字段来说,这将是一个太多的 hack,会使代码太不清楚。 -
@OleV.V.抱歉,我误解了你的部分想法,所以我在评论中提到的关于性能的缺点不存在,因为你的意思是让这些字段瞬态并在克隆后分配它们,这样它们就不会被深度克隆。我实际上正在研究是否可以从克隆主对象的位置访问所有这些字段,以便在克隆后将这些字段设置为原始引用;这实际上可能解决我的问题。
-
如果缺少公共 getter,请注意私有字段仅是类私有,而不是对象私有。因此,对象可以从属于同一类的对象的私有字段中复制引用。你可能觉得这不是最漂亮的解决方案,但它是一种选择。
标签: java serialization clone