Java通过clone()方法创建对象时为什么要实现Cloenable接口和重写clone()方法?

Java通过clone()方法创建对象时为什么要实现Cloenable接口和重写clone()方法?

public class Student implements Cloneable{
    private String name;
    private transient Integer age;

    public Student() {
        System.out.println("无参构造方法!");
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
        System.out.println("有参构造方法!");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

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

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


        // 方式二,调用对象的clone()方法
        // 为了使用clone方法来创建一个对象,该对象对应的类需要实现cloneable接口和重写clone()方法

        Student student = new Student();
        student.setName("小明");
        student.setAge(15);

        Student student2 = (Student) student.clone();
        student2.setAge(14);
        student2.setName("小华");
        System.out.println(student2);
    }
}


根据Cloneable接口源码知

* A class implements the Cloneable interface to
* indicate to the {java.lang.Object#clone()} method that it
* is legal for that method to make a
* field-for-field copy of instances of that class.

翻译:实现了Cloneable接口的类,才表明了Object类的clone()方法可以合法地对当前类的实例进行按字段复制。(Object类是所有类的父类)。

也就是说,只有类实现了Cloneable接口,该类调用clone()方法时才能合法地对类的实例进行按字段复制。



* Invoking Object's clone method on an instance that does not implement the
* Cloneable interface results in the exception
* CloneNotSupportedException being thrown.

翻译:类的实例如果没有实现Cloneable接口而去调用Object.clone()方法时会抛出CloneNotSupportedException异常



* By convention, classes that implement this interface should override
* Object.clone (which is protected) with a public method.
* See { java.lang.Object#clone()} for details on overriding
this
* method.


翻译:按照惯例,实现了这个接口的类应当重写Object.clone()方法(因为Object.clone()方法访问控制符类型为protected的)为public类型。

关于更多clone()方法的细节去看java.lang.Objectclone()方法。


上面的描述已经说明了为什么使用clone()方法创建对象时要实现Cloneable接口,但是为什么也要重写java.lang.Object.clone()方法呢?

         查看java.lang.Object.clone()方法源码

protected native Object clone() throws CloneNotSupportedException;

   可知 java.lang.Object.clone()方法只是进行了声明,并没有实现,因此Object类的子类在调用clone()方法时,需要重写java.lang.Object.clone()方法。


同时,根据《疯狂java讲义》中关于访问控制符的描述:


private(当前类访问权限):如果类里的一个成员(包括成员变量、方法和构造器等)使用private访问控制符来修饰,则这个成员只能当前类的内部被访问。很显然,这个访问控制符用于修饰成员变量就可以把成员变量隐藏在该类的内部。


default(包访问权限):如果类里的一个成员(包括成员变量、方法和构造器)或者一个外部类不适用任何访问控制符修饰,就称它是包访问权限的,default访问控制的成员或外部类可以被相同包下的其他类访问。 


protected(子类访问权限):如果一个成员(包括成员变量、方法和构造器等)使用protected访问控制符修饰,那么这个成员既可以被同一个包中的其他类访问,也可以给不同包中的子类访问。在通常情况下,如果使用protected来修饰一个方法,通常是希望其子类来重写这个方法。


public(公共访问权限):这是一个最宽松的访问控制级别,如果一个成员(包括成员变量、方法和构造器等)或者一个外部类使用public访问控制符修饰,那么这个成员或外部类就可以被所有类访问,不管访问类和被访问类是否处于同一个包中,是否具有父子继承关系。


    从上面的描述中可知,Object类的clone方法用protected关键字修饰,目的是为了让子类重写该方法。但是,似乎并没有解释的很清楚,如果使用public关键字修饰会怎样。

所以,如果大家有更好的解释,欢迎一起讨论!



参考资料
1.java jdk1.8.0_151
源码

2.《疯狂java讲义》第四版 李刚



猜你喜欢

转载自blog.51cto.com/10855700/2497602