Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 关于深度克隆_Java - Fatal编程技术网

Java 关于深度克隆

Java 关于深度克隆,java,Java,当我运行下面的代码时,为什么会抛出这个错误 Exception in thread "main" java.lang.CloneNotSupportedException: Student at java.lang.Object.clone(Native Method) at Student.clone(Student.java:44) at StudentApp.main(StudentApp.java:10) 这是我的主要课程: public static void

当我运行下面的代码时,为什么会抛出这个错误

Exception in thread "main" java.lang.CloneNotSupportedException: Student
    at java.lang.Object.clone(Native Method)
    at Student.clone(Student.java:44)
    at StudentApp.main(StudentApp.java:10)
这是我的主要课程:

public static void main(String[] args) throws CloneNotSupportedException {

    Address address = new Address("湖南省长沙市林科大","1234567",20);
    Student stu = new Student("诸葛亮量",20);
    stu.setAddress(address);

    Student stu2 = (Student)stu.clone();
    stu2.setAddress(new Address("湖南省常德市区","484848348",22));

    stu2.setName("张飞飞");
    stu2.setAge(23);
    stu.sayHi();
    stu2.sayHi();
}
这是学生班:

public class Student{

    private String name;
    private int age;
    private Address address;

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    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;
    }

    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public Student() {
        super();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public void sayHi() {
        System.out.println("大家好,我是" + this.getName() + "同学,我今年" + this.getAge()
                + "岁了……我的HashCode是:" + this.hashCode()+"。我家庭住址是"+address.getAddress()+",家庭住址的HashCode为:"+address.hashCode());
    }

}
这是地址类:

public class Address {

    private String address;
    private String tel;
    private int roadNum;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public int getRoadNum() {
        return roadNum;
    }

    public void setRoadNum(int roadNum) {
        this.roadNum = roadNum;
    }

    public Address() {
        super();
    }

    public Address(String address, String tel, int roadNum) {
        super();
        this.address = address;
        this.tel = tel;
        this.roadNum = roadNum;
    }

}

在未实现的实例上调用对象的克隆方法 可克隆接口导致异常 正在抛出CloneNotSupportedException

您是否尝试让您的学生类实现可克隆接口?

来自

在未实现的实例上调用对象的克隆方法 可克隆接口导致异常 正在抛出CloneNotSupportedException


您是否尝试让您的学生类实现可克隆接口?

学生需要实现可克隆。

学生需要实现可克隆。

与其尝试使用克隆,不如编写一个复制构造函数,以获取学生实例并单独复制其字段。那么你就不必担心克隆的语义了。在您的示例中,这意味着地址上也有一个副本构造函数,因为学生有一个地址字段

约书亚·布洛赫(Joshua Bloch)阅读了《为什么应该避免克隆人》

public class Student {

    final private String name;
    final private int age;
    final private Address address;

    public Address getAddress() {
        return address;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public Student(Student copyStudent) {
        this.name = new String(copyStudent.getName());
        this.age = copyStudent.getAge();
        this.address = new Address(copyStudent.getAddress());
    }
}
来自有效Java

复制构造函数方法及其静态工厂变体有许多优点 与可克隆/克隆相比的优势:它们不依赖于易发生风险的 语言外客体生成机制;他们不要求 无法强制遵守记录不良的公约;他们没有 与最终字段的正确使用相冲突;他们不需要 客户端捕获不必要的已检查异常;它们提供了一个 客户端的静态类型化对象。虽然不可能把 复制接口中的构造函数或静态工厂,Cloneable无法 函数用作接口,因为它缺少公共克隆方法。 因此,您不会因为使用副本而放弃接口功能 构造函数而不是克隆方法。此外,复制构造函数 或者静态工厂可以接受类型为适当的参数 类实现的接口。例如,所有通用 按照惯例,集合实现提供了一个副本构造函数 其参数的类型为Collection或Map。基于接口的拷贝 构造函数允许客户端选择 复制,而不是强制客户机接受 原著。例如,假设您有一个LinkedList l 要将其复制为ArrayList。克隆方法不提供此功能 功能,但使用复制构造函数很容易:新建 ArrayList。考虑到与Cloneable相关的所有问题,它 可以肯定地说,其他接口不应该扩展它 为继承项15设计的类不应实现它。 由于它的许多缺点,一些专家程序员 选择“从不覆盖克隆方法”和“从不调用克隆方法” 也许除了廉价复制阵列之外。要知道,如果你不 至少在类上提供行为良好的受保护克隆方法 设计用于继承,子类不可能 实现可克隆性


与其尝试使用克隆,不如编写一个复制构造函数,以获取学生的实例并单独复制其字段。那么你就不必担心克隆的语义了。在您的示例中,这意味着地址上也有一个副本构造函数,因为学生有一个地址字段

约书亚·布洛赫(Joshua Bloch)阅读了《为什么应该避免克隆人》

public class Student {

    final private String name;
    final private int age;
    final private Address address;

    public Address getAddress() {
        return address;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public Student(Student copyStudent) {
        this.name = new String(copyStudent.getName());
        this.age = copyStudent.getAge();
        this.address = new Address(copyStudent.getAddress());
    }
}
来自有效Java

复制构造函数方法及其静态工厂变体有许多优点 与可克隆/克隆相比的优势:它们不依赖于易发生风险的 语言外客体生成机制;他们不要求 无法强制遵守记录不良的公约;他们没有 与最终字段的正确使用相冲突;他们不需要 客户端捕获不必要的已检查异常;它们提供了一个 客户端的静态类型化对象。虽然不可能把 复制接口中的构造函数或静态工厂,Cloneable无法 函数用作接口,因为它缺少公共克隆方法。 因此,您不会因为使用副本而放弃接口功能 构造函数而不是克隆方法。此外,复制构造函数 或者静态工厂可以接受类型为适当的参数 类实现的接口。例如,所有通用 按照惯例,集合实现提供了一个副本构造函数 其参数的类型为Collection或Map。基于接口的拷贝 构造函数允许客户端选择 复制,而不是强制客户机接受 原著。例如,假设您有一个LinkedList l 要将其复制为ArrayList。克隆方法不提供此功能 功能性,但拷贝起来很容易 建造师:新 ArrayList。考虑到与Cloneable相关的所有问题,它 可以肯定地说,其他接口不应该扩展它 为继承项15设计的类不应实现它。 由于它的许多缺点,一些专家程序员 选择“从不覆盖克隆方法”和“从不调用克隆方法” 也许除了廉价复制阵列之外。要知道,如果你不 至少在类上提供行为良好的受保护克隆方法 设计用于继承,子类不可能 实现可克隆性


学生和地址都需要“深度”克隆,如果您不想在源和目标学生实例中共享地址实例:

class Student implements Cloneable {
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Student result = (Student)super.clone();
        result.setAddress((Address)getAddress().clone());
        return result;       
    }
...
}

class Address implements Cloneable{
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return  (Address) super.clone();
    }
...
}

学生和地址都需要“深度”克隆,如果您不想在源和目标学生实例中共享地址实例:

class Student implements Cloneable {
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Student result = (Student)super.clone();
        result.setAddress((Address)getAddress().clone());
        return result;       
    }
...
}

class Address implements Cloneable{
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return  (Address) super.clone();
    }
...
}

嗨,读这个。编辑你的答案:我在回复你的帖子时编辑了我的答案,为你提供了更多不应该使用克隆的理由。因为复制构造函数也有它的缺陷。本文比有效Java中的第一章要好得多。所以,如果你推荐抄送而不是抄送,因为抄送的缺点,你应该针对私有或受保护的抄送,而不是publicHi,请阅读本文。编辑你的答案:我在回复你的帖子时编辑了我的答案,为你提供了更多不应该使用克隆的理由。因为复制构造函数也有它的缺陷。本文比有效Java中的第一章要好得多。所以,如果你推荐抄送而不是复制,因为复制的缺点,你应该瞄准私有或受保护的抄送,而不是公共的