Does anyone have any suggested or established best practices and naming conventions for copy constructors / factory methods etc in Java? In particular, say I have a class Thing
and I want a method somewhere that returns a new Thing
with the same value as a Thing
passed in (or as the instance if it's an instance method). Would you have this as constructor or a static factory method or instance method? What would you call it?
有没有人对Java中的复制构造函数/工厂方法等有任何建议或建立的最佳实践和命名约定?特别是,假设我有一个类对象,我想要一个方法返回一个新对象,它的值与传入的对象相同(如果是实例方法,则作为实例)。您会把它作为构造函数或静态工厂方法或实例方法吗?你叫它什么?
As per the title, I want to avoid clone()
and Cloneable
.
就标题而言,我希望避免克隆()和克隆。
8 个解决方案
#1
16
Effective Java recommends either of the following:
有效Java建议以下任何一种:
-
A copy constructor (as noted by others):
复制构造函数(如他人所述):
public Item(Item item)
公共项目(项目项)
-
A copy factory method:
一份工厂方法:
public static Item newInstance(Item item)
公共静态项目newInstance(项目)
(Also, no copying for immutables)
(同时,不可复制
The primary difference is that with #1 you choose the actual class of the result, and with #2 the implementer can return a subclass. The semantics of the class may guide you into which one is best.
主要的区别在于,对于#1,您可以选择结果的实际类,对于#2,实现者可以返回一个子类。这门课的语义学可以引导你进入哪一门最好。
#2
3
I would call it a copy method or a copy constructor (as the case may be). If it was a static method, then I would call it a factory.
我将它称为复制方法或复制构造函数(视情况而定)。如果是静态方法,我就叫它工厂。
In terms of what to do, the most flexible and long living option is a copy constructor. This gives subclasses the ability to copy themselves just like the parent.
至于要做什么,最灵活和最长寿的选择是复制构造函数。这使子类能够像父类一样复制自己。
#3
2
I'd do a constructor
我会做一个构造函数
...
public Thing(Thing copyFrom)
{
attr1 = copyFrom.attr1;
attr2 = copyFrom.attr2;
//etc...
}
then when you want to clone it
然后当你想克隆它的时候
Thing copy = new Thing(copy from me);
#4
0
You can overwrite the clone()-method, if you want. Another used practice is a constructor, that takes an object of this type, i.e. new ArrayList(anotherList).
如果需要,可以覆盖clone()方法。另一个常用的实践是构造函数,它接受这种类型的对象,即新的ArrayList(另一个list)。
#5
0
You've got a few options, implement Cloneable
, add a copy constructor but my preferred way is to use a method (static or instance) that has a name which is descriptive of what the copy operation is doing - is it a deep or shallow copy, etc.
您有一些选项,实现Cloneable,添加一个复制构造函数,但是我的首选方法是使用一个方法(静态或实例),该方法的名称描述了复制操作正在进行的操作——它是深度复制还是浅拷贝,等等。
#6
0
Use immutable data structures. The only reason you feel that you need clone()
is that you're mutating your objects in place. Stop doing that. Think about how you can:
使用不可变的数据结构。您认为需要克隆人()的唯一原因是您正在适当地改变您的对象。停止这样做。想想怎么做:
- Make your classes final.
- 最后让你的类。
- Make fields in your classes final and private.
- 使类中的字段成为最终的和私有的。
For example, here's a "setter" for an immutable 3D vector object:
例如,这里有一个不可变3D矢量对象的“setter”:
public Vector3D setX(double x) {
return new Vector3D(x, this.y, this.z);
}
So I guess what I'm saying is... I use copy constructors instead of mutation, and I just name them according to the attribute that I want to modify.
所以我想我说的是……我使用复制构造函数而不是突变,我只是根据我想要修改的属性来命名它们。
#7
0
Another option is to implement the copying method in the source object, e.g.:
另一种选择是在源对象中实现复制方法,例如:
interface Has3DCoords {
void setLocation(double x, double y, double z);
void copyCoordsTo(Has3DCoords dest);
}
You would then implement copying with a piece of code like:
然后,您将使用一段代码实现复制,如:
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;
}
}
This can be useful if:
如果:
- It does not make sense to clone the whole object
- 克隆整个对象是没有意义的
- There is a group of related properties that are often copied as one unit
- 有一组相关的属性通常被复制为一个单元
- You do not want to expose
loc
as a property ofThing
- 您不希望将loc公开为事物的属性
- The number of properties is large (or there are many such groups) so a constructor that required all of them as parameters would be unwieldy.
- 属性的数量很大(或者有很多这样的组),因此需要将所有的属性作为参数的构造函数会很麻烦。
#8
0
This is not the nicest approach to copying objects but the following is sometimes useful if you wish to perform a deep copy of a Serializable object. This avoids having to write copy constuctors, implement Cloneable or writing factory classes.
这不是最好的复制对象的方法,但是如果您希望执行可序列化对象的深度副本,以下方法有时是有用的。这避免了必须编写复制构造函数、实现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();
Don't forget to handle the exceptions and to close the streams nicely.
不要忘记处理异常并很好地关闭流。
#1
16
Effective Java recommends either of the following:
有效Java建议以下任何一种:
-
A copy constructor (as noted by others):
复制构造函数(如他人所述):
public Item(Item item)
公共项目(项目项)
-
A copy factory method:
一份工厂方法:
public static Item newInstance(Item item)
公共静态项目newInstance(项目)
(Also, no copying for immutables)
(同时,不可复制
The primary difference is that with #1 you choose the actual class of the result, and with #2 the implementer can return a subclass. The semantics of the class may guide you into which one is best.
主要的区别在于,对于#1,您可以选择结果的实际类,对于#2,实现者可以返回一个子类。这门课的语义学可以引导你进入哪一门最好。
#2
3
I would call it a copy method or a copy constructor (as the case may be). If it was a static method, then I would call it a factory.
我将它称为复制方法或复制构造函数(视情况而定)。如果是静态方法,我就叫它工厂。
In terms of what to do, the most flexible and long living option is a copy constructor. This gives subclasses the ability to copy themselves just like the parent.
至于要做什么,最灵活和最长寿的选择是复制构造函数。这使子类能够像父类一样复制自己。
#3
2
I'd do a constructor
我会做一个构造函数
...
public Thing(Thing copyFrom)
{
attr1 = copyFrom.attr1;
attr2 = copyFrom.attr2;
//etc...
}
then when you want to clone it
然后当你想克隆它的时候
Thing copy = new Thing(copy from me);
#4
0
You can overwrite the clone()-method, if you want. Another used practice is a constructor, that takes an object of this type, i.e. new ArrayList(anotherList).
如果需要,可以覆盖clone()方法。另一个常用的实践是构造函数,它接受这种类型的对象,即新的ArrayList(另一个list)。
#5
0
You've got a few options, implement Cloneable
, add a copy constructor but my preferred way is to use a method (static or instance) that has a name which is descriptive of what the copy operation is doing - is it a deep or shallow copy, etc.
您有一些选项,实现Cloneable,添加一个复制构造函数,但是我的首选方法是使用一个方法(静态或实例),该方法的名称描述了复制操作正在进行的操作——它是深度复制还是浅拷贝,等等。
#6
0
Use immutable data structures. The only reason you feel that you need clone()
is that you're mutating your objects in place. Stop doing that. Think about how you can:
使用不可变的数据结构。您认为需要克隆人()的唯一原因是您正在适当地改变您的对象。停止这样做。想想怎么做:
- Make your classes final.
- 最后让你的类。
- Make fields in your classes final and private.
- 使类中的字段成为最终的和私有的。
For example, here's a "setter" for an immutable 3D vector object:
例如,这里有一个不可变3D矢量对象的“setter”:
public Vector3D setX(double x) {
return new Vector3D(x, this.y, this.z);
}
So I guess what I'm saying is... I use copy constructors instead of mutation, and I just name them according to the attribute that I want to modify.
所以我想我说的是……我使用复制构造函数而不是突变,我只是根据我想要修改的属性来命名它们。
#7
0
Another option is to implement the copying method in the source object, e.g.:
另一种选择是在源对象中实现复制方法,例如:
interface Has3DCoords {
void setLocation(double x, double y, double z);
void copyCoordsTo(Has3DCoords dest);
}
You would then implement copying with a piece of code like:
然后,您将使用一段代码实现复制,如:
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;
}
}
This can be useful if:
如果:
- It does not make sense to clone the whole object
- 克隆整个对象是没有意义的
- There is a group of related properties that are often copied as one unit
- 有一组相关的属性通常被复制为一个单元
- You do not want to expose
loc
as a property ofThing
- 您不希望将loc公开为事物的属性
- The number of properties is large (or there are many such groups) so a constructor that required all of them as parameters would be unwieldy.
- 属性的数量很大(或者有很多这样的组),因此需要将所有的属性作为参数的构造函数会很麻烦。
#8
0
This is not the nicest approach to copying objects but the following is sometimes useful if you wish to perform a deep copy of a Serializable object. This avoids having to write copy constuctors, implement Cloneable or writing factory classes.
这不是最好的复制对象的方法,但是如果您希望执行可序列化对象的深度副本,以下方法有时是有用的。这避免了必须编写复制构造函数、实现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();
Don't forget to handle the exceptions and to close the streams nicely.
不要忘记处理异常并很好地关闭流。