面试题:深克隆和浅克隆的实现方式
面试官考察点
考察目的:深克隆和浅克隆,考察的是Java基础知识的理解。
考察人群:2到5年开发经验。
背景知识详解
先了解下浅克隆和深克隆的定义:
-
浅克隆:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。
-
深克隆:除去那些引用其他对象的变量,被复制对象的所有变量都含有与原来的对象相同的值。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
如何实现克隆
我么先不管深克隆、还是浅克隆。首先,要先了解如何实现克隆,实现克隆需要满足以下三个步骤
-
对象的类实现Cloneable接口;
-
覆盖Object类的clone()方法(覆盖clone()方法,访问修饰符设为public,默认是protected,但是如果所有类都在同一个包下protected是可以访问的);
-
在clone()方法中调用super.clone();
实现一个克隆
先定义一个score
类,表示分数信息。
public class Score {
private String category;
private double fraction;
public Score() {
}
public Score(String category, double fraction) {
this.category = category;
this.fraction = fraction;
}
//getter/setter省略
@Override
public String toString() {
return "Score{" +
"category='" + category + '\'' +
", fraction=" + fraction +
'}';
}
}
定义一个Person,其中包含Score
属性,来表示这个人的考试分数。
需要注意,Person类是实现了Cloneable接口的,并且重写了clone()
这个方法。
public class Person implements Cloneable{
private String name;
private int age;
private List<Score> score;
public Person() {
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
克隆代码测试,代码逻辑不复杂,就是初始化一个对象mic
,然后基于mic
使用clone
方法克隆出一个对象dylan
。
接着通过修改被克隆对象mic
的成员属性,打印出这两个对象的状态信息。
public class CloneMain {
public static void main(String[] args) throws CloneNotSupportedException {
Person mic=new Person();
Score s1=new Score();
s1.setCategory("语文");
s1.setFraction(90);
Score s2=new Score();
s2.setCategory("数学");
s2.setFraction(100);
mic.setAge(18);
mic.setName("Mic");
mic.setScore(Arrays.asList(s1,s2));
System.out.println("person对象初始化状态:"+mic);
Person dylan=(Person)mic.clone(); //克隆一个对象
System.out.println("打印克隆对象:dylan:"+dylan);
mic.setAge(20);
mic.getScore().get(0).setFraction(70); //修改mic语文分数为70
System.out.println("打印mic:"+mic);
System.out.println("打印dylan:"+dylan);
}
}
执行结果如下:
person对象初始化状态:Person{name='Mic', age=18, score=[Score{category='语文', fraction=90.0}, Score{category='数学', fraction=100.0}]}
打印克隆对象:dylan:Person{name='Mic', age=18, score=[Score{category='语文', fraction=90.0}, Score{category='数学', fraction=100.0}]}
打印mic:Person{name='Mic', age=20, score=[Score{category='语文', fraction=70.0}, Score{category='数学', fraction=100.0}]}
打印dylan:Person{name='Mic', age=18, score=[Score{category='语文', fraction=70.0}, Score{category='数学', fraction=100.0}]}
从结果中可以发现:
-
修改<