Java 使用哪种策略?对象克隆或简单映射

Java 使用哪种策略?对象克隆或简单映射,java,Java,我需要一些帮助。我的代码属于以下模板。 假设customObject有多个property1、property2、…property100 List<CustomObject> customObjectList = /*<method call to external API that returns the said list >*/ if(customObjectList != null && customObjectList.size() >

我需要一些帮助。我的代码属于以下模板。 假设customObject有多个property1、property2、…property100

List<CustomObject> customObjectList = /*<method call to external API that returns the said list >*/
if(customObjectList != null && customObjectList.size() > 0){
    //*** point A ***<clone the Object>
    resultList = <some method that process the above list>(customObjectList)

    if(resultList.size() > 0){
        for(Iterator<Map.Entry<CustomObject, ExternalResponse>> itr = resultList.entrySet().iterator(); itr.hasNext();) {
            //code that modifies the properties in the CustomObjects
            //*** point B ***resetAProperty(<Object clone>)
        }
    }
}
List customObjectList=/**/
if(customObjectList!=null&&customObjectList.size()>0){
//***A点***
结果列表=(customObjectList)
如果(resultList.size()>0){
对于(迭代器itr=resultList.entrySet().Iterator();itr.hasNext();){
//修改CustomObjects中属性的代码
//***B点***重置属性()
}
}
}
在B点,我需要在方法中使用原始对象的一个未修改的特定属性。为此,我有两种策略:

  • 在点A克隆对象,并使用克隆的副本获取 属性,如上面的代码所示。在点A处,使用for循环和A
  • 映射以形成对象名称、属性和原始属性的关联数组 值并遍历它们以获取点处的属性初始值 B
  • 避免克隆,因为它总是需要深度克隆
    .clone()
    尤其是在
    列表上
    几乎总是以眼泪结束,因为您必须
    深度克隆列表中的所有对象、所有引用对象,等等

    深度克隆
    意味着您必须对对象图中的每一个对象进行二进制复制。只需复制一个
    引用
    即可获得一个
    浅拷贝
    ,您将看到对
    引用的
    对象所做的任何更改。只要错过一个属性,你就会有一个地狱般的时间找到那个bug

    解决方案 您应该做的是使所有的
    CustomObject
    实例
    不可变
    ,然后您就不需要担心版本控制,它们永远不会改变,变异将涉及创建一个新的
    不可变的实例和一个完全不同的对象。那你就不用担心版本了


    当然,所有指向其他对象的实例变量也需要是不可变的。这与深度克隆的问题相同,但从另一个角度考虑。一个更易于管理的角度。

    只有当您想要相同类的第二个对象时,才应该进行克隆,而这些对象之间几乎没有差异。如果您希望一个属性保持不变,您可以简单地将其存储在一个临时变量中,或者确保它不会被“修改CustomObjects中属性的代码”更改。我似乎记得,关于克隆的普遍共识是,整个概念已被彻底打破,您应该使用复制构造函数。您仍然必须
    深度克隆
    值,因为复制引用就是对对象的引用。您必须创建对象的新实例,
    java.lang.String
    不可变的
    ,以及
    clone
    执行
    新字符串(oldString)的方式。取决于为什么需要深度克隆第三方类。我只想用“处理它的方法”来阻止它。或者只在其周围公开一个不可变的包装器。在重新阅读代码时,我的修复方法是在修改对象之前保存一个所需的属性,并将其存储在一个
    IdentityHashMap
    中,以便以后可以获得原始值。如果你的代码有一个
    CustomObject
    的虚拟实现,并有一些示例数据和对它们的实际更改,而不是散文式的描述,这会有所帮助。我过去不得不处理对象克隆,并遇到了深层次的克隆问题。清理代码并保持简单的方法是使用上述不可变方法。这种方法使代码保持可读性,并向以后阅读代码的所有人阐明您的意图。使其不可变是正确的编程实践吗?我所需要的只是大量的一个属性,这感觉就像克隆和功能性方法引入了一个新的不希望的复杂性级别,只是为了一个简单的值,我需要在这两种技术上进行比较,看看哪一种被认为是复杂性的噩梦和永无止境的bug的来源。只需谷歌搜索
    Java深度克隆
    等。函数式编程默认使用
    不可变的
    对象。只要看看Erlang,没有可变对象,它工作得很好@重点是你提出的解决方案不是一个小的改变。除非整个对象图是可序列化的,否则您需要一大堆反射代码才能正确地深度克隆对象图,即使这样,您也不确定是否在做一些可笑的事情。(比如,如果对象图包含一些对象,那么克隆就不是一个好主意,比如数据库集合。)没错,而且您必须处理循环引用的可能性,当深度克隆时,循环引用将导致堆栈溢出!即使每个对象都是
    可序列化的
    它也不会为
    克隆
    提供任何东西,它只是一个
    标记
    接口,它没有实现。