克隆:
见名知意,克隆就是把一个东西再复制一份。在Java中,克隆分为浅克隆和深克隆。
Java中克隆的含义:
对象克隆:把A对象的所有属性完全复制给B对象,两个对象(地址值)是不一样的。
浅克隆:
浅克隆是指克隆出来的对象与原对象的引用数据类型的成员变量指向同一个地址。
深克隆:
深克隆是指克隆出来的对象与原对象的引用数据类型的成员变量不指向同一个地址。
那么有朋友就会问:那基本数据类型呢?
这类朋友,你从现在开始就把基本数据类型当作值,不用去想它的地址,既然是值不考虑地址,那么无论是深克隆还是浅克隆,两个对象的基本数据类型的变量一定是毫无关系的,只跟存储到内存中的值有关,一方变动,另一方还是那个值,是不变的,因为毫无关系嘛。而且我想说的是,大家把String和Integer,Doubled等等基本类型的包装类也当作基本数据类型就好。(经过本人实验)
Object类:
Object类里面有实现克隆的方法,叫做clone,被protected修饰,因此只能在同一个包中或者其他包中的子类才可以访问这个方法,返回值是Object。
而且Object的clone方法是浅克隆。
如何用:
- 要使用clone的类实现Cloneable接口,这是一个声明接口。
- 重写clone方法,并且把权限升上去,一般升为public,否则其他类无法调用这个方法。
这样就可以在其它类中调用方法了。
例如:
Student类:
package com.wsh;
public class Student implements Cloneable{
private String name;
private int age;
Subject subject;
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Subject类:
package com.wsh;
public class Subject {
private String name;
public Subject(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
证明其是浅克隆:
package com.wsh;
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Student s = new Student("张三", 18);
Subject subject = new Subject("数学");
s.setSubject(subject); //s的科目是数学。
Student clone =(Student) s.clone();
clone.subject.setName("语文");
System.out.println("s的科目:");
System.out.println(s.getSubject().getName());
System.out.println("clone的科目:");
System.out.println(clone.getSubject().getName());
}
}
结果:
会发现就算一开始给s设置的subject是数学,但是由于地址一样,把clone的subject改变值,s也跟着改变了,意料之中。
那么能不能实现深克隆呢?
能。
1.重写clone方法,升权限。
2.让这个类实现Clonable接口。
3.对里面的引用数据类型:创建一个新的引用数据类型对象,让其属性跟被克隆的对象的属性值一样,并给clone出来的对象的这个属性赋值,这样引用数据类型就是new的了。
例如:
Student类,跟上面的clone方法不同:
package com.wsh;
public class Student implements Cloneable{
private String name;
private Integer age;
Subject subject;
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
Object clone = super.clone();
Student student = (Student) clone;
student.subject=new Subject(student.subject.getName());
return student;
}
}
Subject类和Test类与上面一致。
结果:
ok,这就完成了深克隆!
如果对您有帮助,补药忘记点赞喔~