【问题标题】:How to make a copy on object and not copy its memory address in Java如何在对象上制作副本而不是在 Java 中复制其内存地址
【发布时间】:2015-08-03 20:18:30
【问题描述】:

我正在尝试制作一个 ObjectA 的副本,其中包含另一个 ObjectB,其中还有 6 个其他 ObjectC,但我不想复制它们的任何内存地址,所以如果我更新了任何原始对象稍后,它不会更新副本的值(由所有三个对象组成)。我已经尝试实现 clone() 但这仍然不适用于我正在尝试做的事情。

这就是我想要做的(是的,我知道这看起来很荒谬......):

   void rotateEntireCubeClockwise(){

  System.out.println("Changing view of cube...rotating entire cube clockwise...");
  CubeAlgorithms a2 = clone();
  cube.left = a2.clone().cube.clone().front.clone();
  cube.front = a2.clone().cube.clone().right.clone();
  a2.clone().rotateTopClockwise(1);
  cube.top = a2.clone().cube.clone().top.clone();
  a2.clone().rotateTopCounterClockwise(1);//undo
  a2.clone().rotateLeftClockwise(2);
  cube.back = a2.clone().cube.clone().left.clone();
  a2.clone().rotateLeftCounterClockwise(2);//undo
  a2.clone().rotateBackClockwise(2);
  cube.right = a2.clone().clone().cube.clone().back.clone();
  a2.clone().rotateBackCounterClockwise(2);//undo
  a2.clone().rotateBottomClockwise(1);
  cube.bottom = a2.clone().cube.clone().bottom.clone();
}

public CubeAlgorithms clone() {
    try {
        return (CubeAlgorithms) super.clone();
    } catch (CloneNotSupportedException e) {        
        e.printStackTrace();
        throw new RuntimeException();
    }
}

CubeAlgorithms 包含一个 Cube 对象,Cube 对象包含 6 个 CubeSide 对象(前、左、后、右、下、上)

Cube 和 CubeSides 都包含一个与您在上面看到的类似的克隆方法。

我对这段代码的问题是我希望它顺时针旋转一个立方体,但是它所做的唯一旋转是最后一个。

【问题讨论】:

    标签: java object reference copy clone


    【解决方案1】:

    这通常称为“深拷贝”。没有一种方法可以做到这一点。所有被深度复制的类都必须以一种或另一种形式提供帮助。

    一种方法是使用一个复制构造函数(即构造函数CubeAlgorithms(CubeAlgorithms))对所有传入对象的字段进行深度复制。当然,要对它们进行深层复制,您需要做一些与它们类似的事情——等等。

    如果您的类都是可序列化的并且性能不是一个大问题,另一种方法是序列化和反序列化您的对象。在这里,我不一定指 java 的内置序列化:您可以使用 Jackson 对它们进行 JSON 化,然后将 JSON 字符串读回,等等。

    【讨论】:

    • 实际上,我首先尝试的是复制构造函数。但是,由于某种原因,某些值为 null...
    【解决方案2】:

    我认为您的代码看起来很复杂,因为在该方法中您试图克隆对象并同时对其进行修改(旋转)。

    此外,您多次调用所有对象的“克隆”方法,因此每次您都将创建一个新副本。这可以解释为什么只应用最后一个操作。

    我建议您将操作分开并首先克隆整个立方体(及其内部的所有子对象),然后一旦您有了新的 Cube 对象,然后旋转那个(原来的不会旋转因为第二个对象是一个单独的对象)。

    要克隆对象,您应该在所有类中编写“克隆”方法。 “克隆”方法应该创建一个类的新实例,然后通过克隆它们来填充属性。

    例如在“Cube”类中:

    public Cube clone() {
        Cube newCube = new Cube();
        newCube.front = this.front.clone();
        newCube.back = this.back.clone();
        newCube.left = this.left.clone();
        newCube.right = this.right.clone();
        newCube.top = this.top.clone();
        newCube.bottom = this.bottom.clone();
        return newCube ;
    }
    

    然后您应该以类似的方式实现其他类的“克隆”方法(创建一个新实例,然后使用“this”实例中属性的克隆填充属性)。

    一旦你成功克隆了物体,然后做任何你需要的操作来旋转它(你不需要多次调用“克隆”,只需克隆一次立方体)。

    Cube rotateEntireCubeClockwise(Cube originalCube) {
       Cube newCube = originalCube.clone;
       // now manipulate the "newCube" to make sure it rotates
       // ...
       return newCube;
    }
    

    【讨论】:

    • 感谢您的意见,但为什么我必须从头开始创建一个新副本?如果我这样做,通过使用上述克隆方法,我会不会丢失所有当前值?
    • 您不会丢失当前值,因为在制作副本时,您会使用原始属性的克隆来分配新属性。看一下 Cube 的克隆方法。新的“front”属性使用原始“front”属性的副本进行初始化。
    • 我已经为所有值创建了全新的对象,并将旧的 object.value.clones 复制到新的对象中,但这仍然不起作用。知道为什么吗?
    猜你喜欢
    • 2013-07-06
    • 1970-01-01
    • 2020-04-23
    • 1970-01-01
    • 2019-01-16
    • 1970-01-01
    • 2016-09-28
    • 2013-05-17
    • 2018-11-27
    相关资源
    最近更新 更多