目录
往期回顾,专栏一览
Clonable
对象创建
调用方法
小结:一个对象如何被克隆?
面试问题
代码升华!浅拷贝?
深拷贝实现!
欢迎各路大佬来到 Nick 主页指点
☀️本期文章将学习 [JavaSE] Clonable 克隆,我是博主Nick。✨
✨我的博客主页:Nick_Bears ꧔ꦿ
꧔ꦿ博文内容如对您有所帮助,还请给个点赞 + 关注 + 收藏✨
Clonable
对象创建
创建对象的几种方式?
- new
- 克隆方法
class Person{
public String name;
public Money money = new Money();
public void play() {
System.out.println("敲代码");
}
@Override
public String toString() {
return "Person{" +
"name=" + name +
'}';
}
public class Demo {
public static void main(String[] args) {
Person person = new Person();
Person person1 = person.clone();
}
}
我们发现 clone() 是爆红的,我们查看 clone() 的源码试试
于是改成
Person person1 = (Person)person.clone();
恶心的是仍然报错!!!通过学习,我们知道一个对象实现 clone 说明该对象是可克隆的!于是在被克隆类上实现 Cloneable 接口。
class Person implements Cloneable{
public int age;
public void play(){
System.out.println("玩!");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
//快捷键:Ctrl + O
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
我们发现 clone() 还是爆红的,那么我们抛一下异常
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
//并且抛出异常即可
Person person1 = (Person) person.clone();
}
}
创建对象的几种方式?
- new
- 克隆方法
class Person{
public String name;
public Money money = new Money();
public void play() {
System.out.println("敲代码");
}
@Override
public String toString() {
return "Person{" +
"name=" + name +
'}';
}
public class Demo {
public static void main(String[] args) {
Person person = new Person();
Person person1 = person.clone();
}
}
我们发现 clone() 是爆红的,我们查看 clone() 的源码试试
于是改成
Person person1 = (Person)person.clone();
恶心的是仍然报错!!!通过学习,我们知道一个对象实现 clone 说明该对象是可克隆的!于是在被克隆类上实现 Cloneable 接口。
class Person implements Cloneable{
public int age;
public void play(){
System.out.println("玩!");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
//快捷键:Ctrl + O
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
我们发现 clone() 还是爆红的,那么我们抛一下异常
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
//并且抛出异常即可
Person person1 = (Person) person.clone();
}
}
调用方法
思考:person 默认继承 Object,为什么通过引用不能调用克隆方法?
答:可以调用,只是 clone 比较特殊,只是我们必须要重写。
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
我们已经调用了 clone() 方法,他会帮我们做什么事情?产生一个副本!
思考:person 默认继承 Object,为什么通过引用不能调用克隆方法?
答:可以调用,只是 clone 比较特殊,只是我们必须要重写。
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
我们已经调用了 clone() 方法,他会帮我们做什么事情?产生一个副本!
小结:一个对象如何被克隆?
- 必须实现 Cloneable 接口
- 重写 Object 的 clone() 方法
- 调用方法抛异常
输出克隆的对象
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.age = 99;
Person person1 = (Person) person.clone();
System.out.println(person1);
}
}
//输出
Person{age=99}
修改克隆对象的值,查看克隆值和原来的值
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.age = 99;
Person person1 = (Person) person.clone();
System.out.println(person1);
System.out.println("====================");
person1.age=199;
System.out.println(person);
System.out.println(person1);
}
}
//输出
Person{age=99}
====================
Person{age=99}
Person{age=199}
上面这个代码是深拷贝吗?
答:决定是 深拷贝 还是 浅拷贝 不是某一个方法的使用,或者对应哪种数据类型,而是代码的实现,就是你的代码是如何写的,处理过程如何!我只能说在这种情况下这是深拷贝。
- 必须实现 Cloneable 接口
- 重写 Object 的 clone() 方法
- 调用方法抛异常
输出克隆的对象
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.age = 99;
Person person1 = (Person) person.clone();
System.out.println(person1);
}
}
//输出
Person{age=99}
修改克隆对象的值,查看克隆值和原来的值
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.age = 99;
Person person1 = (Person) person.clone();
System.out.println(person1);
System.out.println("====================");
person1.age=199;
System.out.println(person);
System.out.println(person1);
}
}
//输出
Person{age=99}
====================
Person{age=99}
Person{age=199}
上面这个代码是深拷贝吗?
答:决定是 深拷贝 还是 浅拷贝 不是某一个方法的使用,或者对应哪种数据类型,而是代码的实现,就是你的代码是如何写的,处理过程如何!我只能说在这种情况下这是深拷贝。
面试问题
- 思考:你知道Clonable接口吗?
- 思考:为啥这接口是个空接口?
- 思考:有啥作用?
答:空接口->标志接口->代表当前类可以被克隆。
- 思考:你知道Clonable接口吗?
- 思考:为啥这接口是个空接口?
- 思考:有啥作用?
答:空接口->标志接口->代表当前类可以被克隆。
代码升华!浅拷贝?
我给 Person 新增了一个 Money 属性
class Money{
public double m = 13.14;
}
class Person implements Cloneable{
public int age;
public Money money = new Money();
public void play(){
System.out.println("玩!");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
}
我们通过图推测下面的代码运行都是13.14
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person1.money.m);
System.out.println("================");
}
//结果
13.14
13.14
================
那么我们现在来改掉一个值,可想而知都是同一个引用
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person1.money.m);
System.out.println("================");
person1.money.m = 1314;
System.out.println(person.money.m);
System.out.println(person1.money.m);
}
//结果
13.14
13.14
================
1314.0
1314.0
对于目前情况来说,这是一个浅拷贝,那么我们如何实现深拷贝呢?我们是不是应该也把 Money 复制一份呢?
我给 Person 新增了一个 Money 属性
class Money{
public double m = 13.14;
}
class Person implements Cloneable{
public int age;
public Money money = new Money();
public void play(){
System.out.println("玩!");
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
}
我们通过图推测下面的代码运行都是13.14
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person1.money.m);
System.out.println("================");
}
//结果
13.14
13.14
================
那么我们现在来改掉一个值,可想而知都是同一个引用
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person1.money.m);
System.out.println("================");
person1.money.m = 1314;
System.out.println(person.money.m);
System.out.println(person1.money.m);
}
//结果
13.14
13.14
================
1314.0
1314.0
对于目前情况来说,这是一个浅拷贝,那么我们如何实现深拷贝呢?我们是不是应该也把 Money 复制一份呢?
深拷贝实现!
我们在上面代码的基础上添加一些代码,对 Money 也连接克隆接口,并且重写
class Money implements Cloneable {
public double m = 13.14;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
这样以后我们就能对 Money 也拷贝一份(在 Person 的方法中)
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person)super.clone();
//把钱也拷贝一份
tmp.money = (Money)this.money.clone();
//return super.clone();
return tmp;
}
此时我们再次测试刚刚的方法
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person1.money.m);
System.out.println("================");
person1.money.m = 1314;
System.out.println(person.money.m);
System.out.println(person1.money.m);
}
//运行结果
13.14
13.14
================
13.14
1314.0
代码一览
package 接口.常用接口.Clonable;
class Money implements Cloneable{
public double m = 10000;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
public String name;
public Money money = new Money();
public void play() {
System.out.println("玩王者");
}
@Override
public String toString() {
return "Person{" +
"name=" + name +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp =(Person)super.clone();
tmp.money = (Money) this.money.clone();
// return super.clone();
return tmp;
}
}
public class Demo {
public static void main1(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.name = "Nick";
Person person1 = (Person) person.clone();
System.out.println(person1);
System.out.println("============================");
person1.name = "Nicks";
System.out.println(person1);
System.out.println(person);
//执行结果
// Person{name=Nick}
//============================
// Person{name=Nicks}
// Person{name=Nick}
}
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person1.money.m);
System.out.println("===============================");
person1.money.m = 999999;
System.out.println(person.money.m);
System.out.println(person1.money.m);
//运行结果(重写接口前)
// 10000.0
// 10000.0
// ==============================
// 999999.0
// 999999.0
}
//运行结果(重写接口后)
// 10000.0
// 10000.0
// ===============================
// 10000.0
// 999999.0
}
我们在上面代码的基础上添加一些代码,对 Money 也连接克隆接口,并且重写
class Money implements Cloneable {
public double m = 13.14;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
这样以后我们就能对 Money 也拷贝一份(在 Person 的方法中)
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp = (Person)super.clone();
//把钱也拷贝一份
tmp.money = (Money)this.money.clone();
//return super.clone();
return tmp;
}
此时我们再次测试刚刚的方法
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person1.money.m);
System.out.println("================");
person1.money.m = 1314;
System.out.println(person.money.m);
System.out.println(person1.money.m);
}
//运行结果
13.14
13.14
================
13.14
1314.0
代码一览
package 接口.常用接口.Clonable;
class Money implements Cloneable{
public double m = 10000;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
public String name;
public Money money = new Money();
public void play() {
System.out.println("玩王者");
}
@Override
public String toString() {
return "Person{" +
"name=" + name +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person tmp =(Person)super.clone();
tmp.money = (Money) this.money.clone();
// return super.clone();
return tmp;
}
}
public class Demo {
public static void main1(String[] args) throws CloneNotSupportedException {
Person person = new Person();
person.name = "Nick";
Person person1 = (Person) person.clone();
System.out.println(person1);
System.out.println("============================");
person1.name = "Nicks";
System.out.println(person1);
System.out.println(person);
//执行结果
// Person{name=Nick}
//============================
// Person{name=Nicks}
// Person{name=Nick}
}
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person) person.clone();
System.out.println(person.money.m);
System.out.println(person1.money.m);
System.out.println("===============================");
person1.money.m = 999999;
System.out.println(person.money.m);
System.out.println(person1.money.m);
//运行结果(重写接口前)
// 10000.0
// 10000.0
// ==============================
// 999999.0
// 999999.0
}
//运行结果(重写接口后)
// 10000.0
// 10000.0
// ===============================
// 10000.0
// 999999.0
}


![[JavaSE] Clonable(深克隆,浅克隆) [JavaSE] Clonable(深克隆,浅克隆)](http://www.mshxw.com/aiimages/31/983553.png)
