Java Cloneable接口的深拷贝与浅拷贝详解

这篇文章主要为大家详细介绍了Java Cloneable接口的深拷贝与浅拷贝,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

Cloneable接口源码

Cloneable接口:

实现此接口的类——可被推断java.lang.Object的clone()方法可以被合法调用-以实现类实例:属性到属性的拷贝。

如果一个类未实现Cloneable接口,那么调用clone()方法时,会抛出CloneNotSupportedException异常。

通常,实现了Cloneable接口的子类,应当以public访问权限重写clone()方法(尽管java.Object类中的clone方法是protected类型的)

应当认识到:Cloneable接口没有包含clone()方法,因此,如果仅仅是implements了Cloneable接口,那么也是无法正常克隆对象的

[原因:即使是反射性地调用了克隆方法,也不能保证它一定会成功]——个人理解就是:是否重写Clone()方法、或者“浅拷贝与深拷贝”问题的存在所导致的。

class Pet implements Cloneable{ //properties private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } public Pet() { } public Pet(String name) { this.name = name; } @Override public String toString() { return "Pet{" + "name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pet pet = (Pet) o; return Objects.equals(name, pet.name); } @Override public int hashCode() { return Objects.hash(name); } //    @Override //    public Pet clone() { //        try { //            return (Pet)super.clone(); //        } catch (CloneNotSupportedException e) { //            e.printStackTrace(); //        } //        return null; //    } } 

浅拷贝案例

Pet类定义

注意到:Pet类实现了Cloneable接口,但是没有重写Clone()方法(显然:此时Pet类不具备对象克隆的能力)。

class Pet implements Cloneable{ //properties private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } public Pet() { } public Pet(String name) { this.name = name; } @Override public String toString() { return "Pet{" + "name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pet pet = (Pet) o; return Objects.equals(name, pet.name); } @Override public int hashCode() { return Objects.hash(name); } //    @Override //    public Pet clone() { //        try { //            return (Pet)super.clone(); //        } catch (CloneNotSupportedException e) { //            e.printStackTrace(); //        } //        return null; //    } } 

Person类定义

注意到:Person类实现了Cloneable接口,也重写Clone()方法。那么,是否Person类就具备了对象克隆的能力呢?(由于浅拷贝问题的存在,认为这种对象克隆能力是不完整的、有缺陷的)。

class Pet implements Cloneable{ //properties private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } public Pet() { } public Pet(String name) { this.name = name; } @Override public String toString() { return "Pet{" + "name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Pet pet = (Pet) o; return Objects.equals(name, pet.name); } @Override public int hashCode() { return Objects.hash(name); } //    @Override //    public Pet clone() { //        try { //            return (Pet)super.clone(); //        } catch (CloneNotSupportedException e) { //            e.printStackTrace(); //        } //        return null; //    } } 

浅拷贝问题-代码测试

为什么说:此时Person类的对象克隆能力是不完整的、有缺陷的?因为此时,在通过Person对象调用clone()方法,克隆对象时,其成员属性pet(Pet类的对象)值的克隆,仅仅是对堆区内存地址的简单拷贝。

即:说白了,Person对象和克隆出来的对象,其pet属性值共享同一块堆区内存。——问题显而易见:当对克隆出来的对象的pet属性进行set操作时,显然会影响到原始Person对象的pet属性值。

代码演示如下:

  //methods public static void main(String[] args) throws CloneNotSupportedException { testPerson(); } public static void testPerson() throws CloneNotSupportedException { Person p=new Person("张三",14,new Pet("小黑")); System.out.println(p); Person clone = (Person)p.clone(); System.out.println(clone); System.out.println(p.equals(clone)); System.out.println(p.getPet()==clone.getPet()); System.out.println("************"); clone.setAge(15); System.out.println(p); System.out.println(clone); System.out.println(p.equals(clone)); System.out.println("************"); clone.getPet().setName("小黄"); System.out.println(p); System.out.println(clone); System.out.println(p.equals(clone)); System.out.println(p.getPet()==clone.getPet()); } 

在这里插入图片描述

深拷贝案例

那么,如何实现深拷贝呢?关键就在上述案例中,被注释的几行代码中。

Pet类重写clone()方法

在这里插入图片描述

Person的clone()方法中调用Pet的clone方法

在这里插入图片描述

浅拷贝问题解决-深拷贝代码测试

测试代码不变,再次运行:

在这里插入图片描述

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注0133技术站的更多内容!      

以上就是Java Cloneable接口的深拷贝与浅拷贝详解的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » Java