小白都能看得懂的Java类克隆
一个对象同时赋值给多个变量,当修改其中某一个对象时,其他对象的值会不会被修改?
答案时肯定的,因为引用的只是某一个对象的地址值,这几个对象存储的只是该对象在内存中的地址,所以他们访问的是同一个值。
实例:
public class User {
private String name;
private int age;
}
public class TestMain {
public static void main(String[] args) {
User user1 = new User();
user1.setName("小王");
user1.setAge(18);
System.out.println(user1);
User user2 = user1;
user2.setName("小刘");
user2.setAge(20);
System.out.println(user1);
}
}
//结果
User{name='小王', age=18}
User{name='小刘', age=20}
今天在项目中就范了这样的错误,在需要临时记录某一个对象时直接进行了赋值,导致后面出
bug
找了好半天。
在遇到需要临时记录某一对象时,可以采用对象克隆的方法,下面试试对象克隆。
对象的克隆
一、浅克隆
要求实体类实现cloneable
接口并重写clone()
方法
克隆的对象和原对象共用引用类型,即修改克隆对象的引用类型,原对象的引用类型也会被修改,例如:
public class User implements Cloneable{
private String name;
private int age;
private School school;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class School {
private String schoolName;
private String address;
}
public class TestMain {
public static void main(String[] args) throws CloneNotSupportedException {
User user1 = new User();
School school = new School();
school.setSchoolName("太阳小学");
school.setAddress("北京");
user1.setName("小王");
user1.setAge(18);
user1.setSchool(school);
System.out.println(user1);
User clone = (User)user1.clone();
clone.setName("小陈");
clone.setAge(22);
clone.getSchool().setAddress("上海");
clone.getSchool().setSchoolName("月亮小学");
System.out.println("user1:"+user1);
System.out.println("clone:"+clone);
}
}
//结果
user1:User{name='小刘', age=20, school=School{schoolName='月亮小学', address='上海'}}
clone:User{name='小陈', age=22, school=School{schoolName='月亮小学', address='上海'}}
分析:可以看到在克隆后的对象中设置name和age并不会影响原来对象的属性值,但是在修改school属性时则造成了影响,这就是浅克隆,只能克隆非引用类型的属性,但是String
是个特殊的例子,因为string
是被final修饰的暂时把他看作数据类型,后面我会再研究一下这个问题。
如果想要让对象中的引用类型也被克隆怎么办??
二、深度克隆
要求类中的引用类型也实现clone
接口,并重写clone()
方法:
public class User implements Cloneable{
private String name;
private int age;
private School school;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class School implements Cloneable{
private String schoolName;
private String address;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class TestMain {
public static void main(String[] args) throws CloneNotSupportedException {
User user1 = new User();
School school = new School();
school.setSchoolName("太阳小学");
school.setAddress("北京");
user1.setName("小王");
user1.setAge(18);
user1.setSchool(school);
System.out.println(user1);
User clone = (User)user1.clone();
clone.setName("小陈");
clone.setAge(22);
clone.getSchool().setAddress("上海");
clone.getSchool().setSchoolName("月亮小学");
System.out.println("user1:"+user1);
System.out.println("clone:"+clone);
}
}
//结果
user1:User{name='小刘', age=20, school=School{schoolName='月亮小学', address='上海'}}
clone:User{name='小陈', age=22, school=School{schoolName='月亮小学', address='上海'}}
但是明明重写了
school
的clone
方法为什么没有用呢?原因是虽然
school
重写了clone
方法但是没有谁调用过,也就不会起作用了,那要在哪调用呢?当然是哪里定义哪里调用了,所以就需要在user
类中去调用school
的clone
方法。
修改后:
public class User implements Cloneable{
private String name;
private int age;
private School school;
@Override
protected Object clone() throws CloneNotSupportedException {
User user = (User)super.clone();
School school = (School)school.clone();
user.setSchool(school);
return user;
}
}
public class School implements Cloneable{
private String schoolName;
private String address;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class TestMain {
public static void main(String[] args) throws CloneNotSupportedException {
User user1 = new User();
School school = new School();
school.setSchoolName("太阳小学");
school.setAddress("北京");
user1.setName("小王");
user1.setAge(18);
user1.setSchool(school);
System.out.println(user1);
User clone = (User)user1.clone();
clone.setName("小陈");
clone.setAge(22);
clone.getSchool().setAddress("上海");
clone.getSchool().setSchoolName("月亮小学");
System.out.println("user1:"+user1);
System.out.println("clone:"+clone);
}
}
//结果
user1:User{name='小刘', age=20, school=School{schoolName='太阳小学', address='北京'}}
clone:User{name='小陈', age=22, school=School{schoolName='月亮小学', address='上海'}}
以上就是Java中的克隆的用法,我也作为一次填坑记录一下!!peace!!