10

我试图了解 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);
4

5 回答 5

9

如果需要副本,请调用 clone(),如果不需要,请调用构造函数。
标准的克隆方法 (java.lang.Object.clone()) 无需调用构造函数即可创建对象的浅表副本。如果你需要一个深拷贝,你必须重写 clone 方法。
并且不用担心性能。
性能取决于克隆方法和构造函数的内容,而不是使用的技术(新的或克隆的)本身。

编辑:克隆和构造函数并不是真的可以相互替代,它们满足不同的目的

于 2015-02-25T21:15:05.023 回答
6

我为类创建了简单的基准Person

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%。

于 2017-07-13T07:43:07.323 回答
5
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 毫秒

于 2017-06-19T11:59:47.437 回答
1

约阿希姆是对的。如果您需要复制使用克隆,如果您需要一个单独的对象(对于一个单独的人),您应该使用new并创建一个新对象。

“更多性能”是主观的,在这里可能不是正确的术语。克隆中发生的是底层对象是共享的,即它们对同一内存位置有 2 个单独的引用。如此有效地节省了创建对象和内存。还记得深拷贝/浅拷贝吗?

于 2015-02-27T09:51:35.150 回答
1

我的要求是为一个类创建 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

所以,我不认为对这些有巨大的性能影响,但会根据我的要求提供更简洁的代码。

于 2017-08-24T06:43:47.913 回答