我试图了解java中clone()方法下面发生了什么,我想知道如何做一个新的调用
public class Person implements Cloneable {
private String firstName;
private int id;
private String lastName;
//constructors, getters and setters
@Override
protected Object clone() throws CloneNotSupportedException {
Person p = (Person) super.clone();
return p;
}
}
这是我的克隆代码我想知道下面发生了什么,以及新呼叫之间的区别是什么。
这是我的客户代码
Person p = new Person("John", 1, "Doe");
Person p2 = null;
try {
p2 = (Person) p.clone();
} catch (CloneNotSupportedException ex) {
Logger.getLogger(clientPrototype.class.getName()).log(Level.SEVERE, null, ex);
}
p2.setFirstName("Jesus");
System.out.println(p);
System.out.println(p2);
答案 0 :(得分:5)
如果您需要副本,请调用clone(),否则请调用构造函数。
标准克隆方法(java.lang.Object.clone())在不调用构造函数的情况下创建对象的浅表副本。如果需要深层复制,则必须覆盖克隆方法。
并且不要担心性能。
性能取决于克隆方法和构造函数的内容,而不是来自使用的技术(新的或克隆)本身。
编辑:克隆和构造函数不是彼此真正的替代品,它们满足不同目的
答案 1 :(得分:4)
public void testPerformance(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
long start = System.currentTimeMillis();
for(int i = 0; i < 1000000; i++){
SimpleDateFormat localSdf = (SimpleDateFormat)sdf.clone();
}
System.out.println("Cloning : " + (System.currentTimeMillis() - start) + " ms");
start = System.currentTimeMillis();
for(int i = 0; i < 1000000; i++){
Object localSdf = new SimpleDateFormat("yyyy-MM-dd");
}
System.out.println("Creating : " + (System.currentTimeMillis() - start) + " ms");
}
克隆:302毫秒 创建:885毫秒
答案 2 :(得分:3)
我为班级Person
创建了simple benchmark:
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
得到以下结果:
Benchmark Mode Cnt Score Error Units
MyBenchmark.viaClone avgt 10 10.041 ± 0.059 ns/op
MyBenchmark.viaNew avgt 10 7.617 ± 0.113 ns/op
这个简单的基准测试表明,实例化新对象并从源对象设置相应的属性所需的时间比克隆它少25%。
答案 3 :(得分:1)
约阿希姆是对的。如果您需要复制使用克隆,如果您需要一个单独的对象(对于一个单独的人),您应该使用new
并创建一个新的对象。
'更多表现'是主观的,可能不是正确的术语。克隆中发生的是底层对象是共享的,即它们对同一内存位置有2个单独的引用。因此,您可以有效地节省创建对象和内存。还记得深拷贝/浅拷贝吗?
答案 4 :(得分:0)
我的要求是为一个类创建1000个对象。所有这些对象共享大多数属性。因此,我决定创建一个具有公共属性的基础对象,并将其克隆到克隆对象集对象特定属性上。这会对性能产生什么影响?我尝试了与上面相同的例子,采用不同的方法,我注意到没有太多稳定的性能差异。这是我的代码和结果。
import java.util.*;
import java.util.stream.*;
import java.text.*;
public class Test{
public static void main(String[] args){
try{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
long start = System.currentTimeMillis();
SDFHolder holder = new SDFHolder();
holder.setSdf(sdf);
for(int i = 0; i < 1000000; i++){
SDFHolder locHolder = (SDFHolder)holder.clone();
}
System.out.println("Cloning : " + (System.currentTimeMillis() - start) + " ms");
start = System.currentTimeMillis();
for(int i = 0; i < 100000000; i++){
SDFHolder locHolder = new SDFHolder();
locHolder.setSdf(sdf);
}
System.out.println("Creating : " + (System.currentTimeMillis() - start) + " ms");
} catch(Exception e){
e.printStackTrace();
}
}
}
class SDFHolder implements Cloneable {
private SimpleDateFormat sdf;
public void setSdf(SimpleDateFormat sdf){
this.sdf = sdf;
}
public SimpleDateFormat getSdf(){
return this.sdf;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
结果是
C:\Users\thangaraj.s\Desktop>java Test
Cloning : 15 ms
Creating : 0 ms
C:\Users\thangaraj.s\Desktop>java Test
Cloning : 16 ms
Creating : 0 ms
C:\Users\thangaraj.s\Desktop>java Test
Cloning : 0 ms
Creating : 15 ms
C:\Users\thangaraj.s\Desktop>java Test
Cloning : 0 ms
Creating : 16 ms
C:\Users\thangaraj.s\Desktop>java Test
Cloning : 16 ms
Creating : 0 ms
因此,我不认为这些会对这些产生巨大的性能影响,但在我的要求下会提供更简洁的代码。