目录Cloneable接口源码浅拷贝案例Pet类定义Person类定义浅拷贝问题-代码测试深拷贝案例Pet类重写clone()方法Person的clone()方法中调用Pet的clo
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类实现了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类实现了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());
}
那么,如何实现深拷贝呢?关键就在上述案例中,被注释的几行代码中。
测试代码不变,再次运行:
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!
--结束END--
本文标题: Java Cloneable接口的深拷贝与浅拷贝详解
本文链接: https://www.lsjlt.com/news/142886.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0