一、这个克隆真的是克隆而已吗?
没错,就是你想像的克隆一个对象,依据已经有的数据,创造一份新的完全一样的数据拷贝
二、他们有什么区别吗?
一、两大区别,浅克隆和深克隆
-
浅克隆:是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象,也就是说对象虽然克隆出来了,但是引用的对象还是那个。
-
深克隆:不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。
四、克隆有什么作用?
看一下下面这段代码
public static void main(String[] args) {
User user = new User();
User u = user;
u.NAME = "new twelvet";
System.out.println(user.NAME);
}
在我想拥有一个一模一样新的对象并对它做出改变的时候,会不会想到这种方式呢?
但,很很明显这种方式明显错误的,因为u是指向了user对象的地址,如果这样操作那么,user的值也是会跟着改变的!!!所以这种方式不可取的
既然如此,这不行,那我重新new一个总行了吧?不不不,要是我需要修改了源对象中的一些信息后,再想要一个一模一的呢???
综上所说,我们需要使用到Cloneable
三、克隆是怎么实现的呢?
1. 步骤
- 实现 C l o n e a b l e \color{red}Cloneable Cloneable接口;
- 重写 c l o n e ( ) \color{red}clone() clone()方法 (覆盖clone()方法,访问修饰符设为public,默认是protected);
- 在clone()方法中调用super.clone();
2.代码
- 首先,我们需要一个作品
public class TwelveT implements Cloneable {
private Developer author;
private String describe = "愚者于成,智者败智。";
public TwelveT(Developer author) {
this.author = author;
}
@Override
protected TwelveT clone() throws CloneNotSupportedException {
return (TwelveT) super.clone();
}
public Developer getAuthor() {
return author;
}
public void setAuthor(Developer author) {
this.author = author;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
@Override
public String toString() {
return "TwelveT{" +
"author='" + author + '\'' +
", describe='" + describe + '\'' +
'}';
}
}
- 其次,我们还需要一个作者 ( 注 意 , 在 这 里 也 实 现 了 C l o n e a b l e 是 因 为 深 克 隆 需 要 用 到 ) \color{red}(注意,在这里也实现了Cloneable是因为深克隆需要用到) (注意,在这里也实现了Cloneable是因为深克隆需要用到)
public class Developer implements Cloneable{
private String name;
public Developer(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Developer{" +
"name='" + name + '\'' +
'}';
}
}
- 然后,我们来进行克隆的演示
浅克隆
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
// 实例一个作者
Developer developer = new Developer("L");
// 实例一个twelve作品
TwelveT twelvet = new TwelveT(developer);
// 浅克隆一个对象
TwelveT twelvet2 = twelvet.clone();
// 对比一下
System.out.println("twelvet:" + twelvet.toString());
System.out.println("twelvet2:" + twelvet2.toString());
// 现在来进行一下修改,却发现的对源对象有影响
developer.setName("盗版");
System.out.println("twelvet:" + twelvet.toString());
System.out.println("twelvet2:" + twelvet2.toString());
}
}
###################################################################################
twelvet:TwelveT{author='Developer{name='L'}', describe='愚者于成,智者败智。'}
twelvet2:TwelveT{author='Developer{name='L'}', describe='愚者于成,智者败智。'}
twelvet:TwelveT{author='Developer{name='盗版'}', describe='愚者于成,智者败智。'}
twelvet2:TwelveT{author='Developer{name='盗版'}', describe='愚者于成,智者败智。'}
####################################################################################
这里的输出看上去是一模一样的对吧,但是他们的hashCode是不一样,可以自己去验证一下哦。
你可以通过
s
e
t
D
e
s
c
r
i
b
e
(
)
\color{red}setDescribe()
setDescribe()方法去改变
t
w
e
l
v
e
t
2
\color{red}twelvet2
twelvet2的描述,但是你不能去修改这个
d
e
v
e
l
o
p
e
r
.
s
e
t
N
a
m
e
(
"
盗
版
者
"
)
\color{red}developer.setName("盗版者")
developer.setName("盗版者")!!!
为什么呢?因为你一修改,那这个twelvet的信息也会跟着改变的,这就是浅克隆。你可以修改克隆的一些类本身的一些属性,但是,你不能去修改源类的指向对象!!!,他们是共同指向的一个作者的,可以说是盗版了,也改了本身的东西,但就是不能够改指向的对象,那么这好像就没什么意义啊,不能改,这就涉及到了我们的深克隆!!!
好说这么多,来看一下我们这个操作图,来加深认知!!!
深克隆
很简单,只需要重写我们的TwelveT下的clone方式即可
public class TwelveT implements Cloneable {
private Developer author;
private String describe = "愚者于成,智者败智。";
public TwelveT(Developer author) {
this.author = author;
}
@Override
protected TwelveT clone() throws CloneNotSupportedException {
TwelveT twelvet = (TwelveT) super.clone();
// 将Developer也进行一次克隆,如此一来源对象将不会受此影响!!!!
twelvet.author = (Developer) author.clone();
return twelvet;
}
public Developer getAuthor() {
return author;
}
public void setAuthor(Developer author) {
this.author = author;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
@Override
public String toString() {
return "TwelveT{" +
"author='" + author + '\'' +
", describe='" + describe + '\'' +
'}';
}
}