是否有人对Java中的复制构造函数/工厂方法等有任何建议或建立的最佳实践和命名约定?特别是,假设我有一个类Thing
,我希望某个方法返回一个新的Thing
,其值与传入的Thing
相同(或者作为实例,如果它是一个实例)方法)。你有这个作为构造函数或静态工厂方法或实例方法?你会怎么称呼它?
根据标题,我想避免clone()
和Cloneable
。
答案 0 :(得分:16)
Effective Java建议使用以下任一项:
复制构造函数(如其他人所述):
公共项目(项目项目)
复制工厂方法:
public static Item newInstance(Item item)
(另外,不要复制不可变的东西)
主要区别在于,使用#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();
不要忘记处理异常并很好地关闭流。