目录
1.什么是克隆对象?
2.为什么要使用克隆对象?
3.克隆对象的使用?
3.1 浅克隆
3.2 深克隆
1.什么是克隆对象?
克隆这个词大家并不陌生,实质就是拷贝对象,形成一个对象的副本。克隆对象就是对已有的一个对象进行拷贝。
进行克隆的目的(意义):被克隆和克隆对象之间完全复制、相互之间没有影响的目的。
2.为什么要使用克隆对象?
在java中,我们使用对象的时候直接去new一个对象就好了,为什么还要克隆对象呢?
当我们new一个对象之后是要对该对象进行初始化的,不然这个对象是空的没有内容。而使用克隆,则会得到一个原对象以及原对象里面包含的内容。例如,你有一个User对象,里面的包含了相关的属性。此时你想要修改里面的某一属性,但又不想破坏原对象里面的数据,此时就可以克隆User这个对象,然后在克隆的这个User对象上进行修改操作。除此,如果你在操作完之后判断一下属性是否更改成功,则使用克隆的对象和原对象做一下对比即可。
3.克隆对象的使用?
3.1 浅克隆
浅克隆就是把原对象中的一些属性值克隆过来。使用clone()方法进行浅克隆。但注意:必须要在被克隆类上实现Cloneable接口,并重写clone方法。若不没有实现该接口,则会抛出CloneNotSupportedException异常!
public class CloneTest1 {
public static void main(String[] args) throws Exception {
//创建原对象,并为原对象中的属性进行赋值,然后打印出结果
User user = new User();
user.setName("张三");
user.setAge(18);
System.out.println("原对象(user)的属性值:");
System.out.println("姓名为:"+user.getName()+",年龄为:"+user.getAge());
//对user对象进行克隆
User user1 = (User) user.clone();
//查看一下克隆对象中的属性值
System.out.println("克隆后user1对象中的属性值:");
System.out.println("姓名为:"+user1.getName()+",年龄为:"+user1.getAge()); //结果和原对象中属性值相同
//对user1对象进行修改
user1.setName("李四");
//查看修改后的结果
System.out.println("user1对象进行修改后的属性值:");
System.out.println("姓名为:"+user1.getName()+",年龄为:"+user1.getAge()); //结果和原对象中属性值相同
}
}
//定义一个User类
//实现Cloneable 接口
class User implements Cloneable {
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;
}
//重写clone方法
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试结果为:
从结果上可以看出,克隆对象user1和原对象user在修改属性数据时,两个对象之间的数据互不受影响。
那么如果后期需要调整代码,需要在原有的user对象中添加一个引用类型Address字段,那么克隆的user1对象会能受到影响吗?能和原对象user中的数据一致吗?
看下面代码演示,在原有基础代码上加入一个Address的类,并分别在User类和Address类中加入重写Object的方法。注意:User类中的引用address字段的权限修饰符为public,否则无法运行!
public class CloneTest1 {
public static void main(String[] args) throws Exception {
//创建原对象,并为原对象中的属性进行赋值,然后打印出结果
Address address = new Address("中国","山东");
User user = new User("张三",18,address);
System.out.println("原对象(user)的属性值:");
System.out.println("姓名为:"+user.getName()+",年龄为:"+user.getAge()+",地址为:"+user.address);
//对user对象进行克隆
User user1 = (User) user.clone();
//查看一下克隆对象中的属性值
System.out.println("克隆后user1对象中的属性值:");
System.out.println("姓名为:"+user1.getName()+",年龄为:"+user1.getAge()+",地址为:"+user.address); //结果和原对象中属性值相同
//对user对象进行修改
user1.setName("李四");
user1.getAddress().setCity("北京");
//查看修改后的结果
System.out.println("user1对象进行修改后的属性值:");
System.out.println("姓名为:"+user1.getName()+",年龄为:"+user1.getAge()+",地址为:"+user1.address); //结果和原对象中属性值相同
System.out.println("姓名为:"+user.getName()+",年龄为:"+user.getAge()+",地址为:"+user.address);
}
}
//定义一个User类
class User implements Cloneable {
private String name;
private int age;
public 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;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", address=" + address + "]";
}
public User(String name,int age,Address address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
//重写clone方法
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
//定义一个address类
class Address{
private String country;
private String city;
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address [country=" + country + ", city=" + city + "]";
}
public Address(String country,String city) {
super();
this.country = country;
this.city = city;
}
}
打印其结果为:
浅克隆只是克隆原对象中的引用类型指向,并非克隆了原对象中的全部数据。
3.2 深克隆
深克隆和浅克隆的区别在于:浅克隆只克隆了原对象的引用类型的指向。深克隆则是克隆了原对象的所有。也就是说像上面案例所示,如果使两个对象之间互不影响,则使用深克隆。
深克隆的使用:在引用类型所在的类使其实现Cloneable接口,并使用public修饰符重写Clone()方法。
代码如下:
在Address类中进项代码修改:
class Address implements Cloneable{ //实现Cloneable接口
private String country;
private String city;
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Address [country=" + country + ", city=" + city + "]";
}
public Address(String country,String city) {
super();
this.country = country;
this.city = city;
}
//重写clone()方法,并使用public修饰符
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
打印其结果为:
从结果上看原对象不会因为克隆对象的改变而改变了。做到了完全拷贝,但互不影响的目的。