如果你不用Java克隆那么你做了什么,你怎么称呼它?

时间:2009-07-06 13:22:52

标签: java oop

是否有人对Java中的复制构造函数/工厂方法等有任何建议或建立的最佳实践和命名约定?特别是,假设我有一个类Thing,我希望某个方法返回一个新的Thing,其值与传入的Thing相同(或者作为实例,如果它是一个实例)方法)。你有这个作为构造函数或静态工厂方法或实例方法?你会怎么称呼它?

根据标题,我想避免clone()Cloneable

8 个答案:

答案 0 :(得分:16)

Effective Java建议使用以下任一项:

  1. 复制构造函数(如其他人所述):

    公共项目(项目项目)

  2. 复制工厂方法:

    public static Item newInstance(Item item)

  3. (另外,不要复制不可变的东西)

    主要区别在于,使用#1选择结果的实际类,使用#2,实​​现者可以返回子类。课程的语义可以指导你哪一个是最好的。

答案 1 :(得分:3)

我称之为复制方法或复制构造函数(视情况而定)。如果它是静态方法,那么我将其称为工厂。

就做什么而言,最灵活和长寿的选择是复制构造函数。这使子类能够像父类一样复制自己。

答案 2 :(得分:2)

我会做一个构造函数

...
public Thing(Thing copyFrom)
{
    attr1 = copyFrom.attr1;
    attr2 = copyFrom.attr2;
    //etc...
}

然后当你想要克隆它

Thing copy = new Thing(copy from me);

答案 3 :(得分:0)

如果需要,您可以覆盖clone() - 方法。另一种使用的做法是构造函数,它接受这种类型的对象,即new ArrayList(anotherList)

答案 4 :(得分:0)

你有几个选项,实现Cloneable,添加一个复制构造函数,但我首选的方法是使用一个方法(静态或实例),其名称描述了复制操作的作用 - 是深层还是浅层副本等。

答案 5 :(得分:0)

使用immutable data structures。您认为需要clone()的唯一原因是您正在改变您的对象。别那样做。想想你怎么做:

  • 让你的课程最终成功。
  • 让您的课程中的字段成为最终和私有。

例如,这是一个不可变3D矢量对象的“setter”:

public Vector3D setX(double x) {
  return new Vector3D(x, this.y, this.z);
}

所以我想我所说的是......我使用复制构造函数而不是变异,我只是根据我想要修改的属性命名它们。

答案 6 :(得分:0)

另一种选择是在 source 对象中实现复制方法,例如:

interface Has3DCoords {
    void setLocation(double x, double y, double z);

    void copyCoordsTo(Has3DCoords dest);
}

然后,您将使用以下代码实现复制:

class Thing implements Has3DCoords {
    private Point3D loc;
    // ...

    void setLocation(double x, double y, double z) {
        loc.setLocation(x, y, z);
        // or: loc = new Point3D(x, y, z);
    }

    void copyCoordsTo(Has3DCoords dest) {
        loc.copyCoordsTo(dest);
        // or: dest.setLocation(loc.getX(), loc.getY(), loc.getZ());
    }

    OtherThing createOtherThing() {
        OtherThing result = new OtherThing();
        this.copyCoordsTo(result);
        return result;
    }
}

如果符合以下条件,这将非常有用:

  • 克隆整个对象没有意义
  • 有一组相关属性经常被复制为一个单元
  • 您不希望将loc公开为Thing
  • 的属性
  • 属性数量很大(或者有很多这样的组),因此需要所有这些属性作为参数的构造函数会很笨重。

答案 7 :(得分:0)

这不是复制对象的最佳方法,但如果您希望执行 Serializable 对象的深层复制,则以下内容有时非常有用。这避免了必须编写复制构造函数,实现Cloneable或编写工厂类。

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);

//Serializes the input object
oos.writeObject(input);

ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);

//Copy of the input object
Object output = ois.readObject();

不要忘记处理异常并很好地关闭流。