克隆如何比对象创建具有更高的性能

How clone has more performance than object creation

我想了解 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);

如果需要复制,调用clone(),如果不需要,调用构造函数。
标准克隆方法 (java.lang.Object.clone()) 在不调用构造函数的情况下创建对象的浅表副本。如果需要深拷贝,则必须重写克隆方法。
不用担心性能。
性能取决于克隆方法和构造函数的内容,而不是所用技术(新的或克隆的)本身。

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

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

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

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 毫秒

我已经为 class 创建了 simple benchmark 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%。

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

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