文章目录
- 1、为什么要clone
- 2、new 对象和 clone 对象的区别
- 3、clone 对象的使用
- 1) 我们 先看 一下 赋值引用;
- 2)下面我们看一下克隆一个对象:
- 4、clone 分为 浅拷贝 和 深拷贝
- 1) 浅拷贝
- 2)、深拷贝
- 3)、浅拷贝示例
- 4)、深拷贝的例子
1、为什么要clone
当一个对象需要被多人操作,但是又不相互影响,需要保持原对象的状态,这时就会克隆出许多不同的对象。
2、new 对象和 clone 对象的区别
new 操作 本质是操作内存。程序在执行new操作的时候,首先看到的是new
操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存后,在调用构造函数,填充对象的各个域,这一步叫做对象的初始化。构造方法创建完成之后,可以吧他的引用(地址)发布到外部,就可以在外部引用操纵这个对象。
clone 在第一步 和new 相似,都是分配内存,调用clone 方法时,分配的内存和原对象(调用clone方法的原对象),然后再使用对象中对应的各个域,填充新的对象的域,填充完成后,clone 方法返回,一个新的相同的对象被创建,同样可以把新的对象那个的引用发布到外部。
3、clone 对象的使用
1) 我们 先看 一下 赋值引用;
package com.example.lum.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Person testObjectOne;
Person testObjectTwo;
testObjectOne = new Person(28,"lu"); //新建 一个对象 one
testObjectTwo = testObjectOne; //将 one 赋值给 Twos
System.out.println("``````````````");
System.out.println(testObjectOne);
System.out.println(testObjectTwo);
System.out.println("``````````````");
}
class Person {
private int age;
private String name ;
public Person(int age,String name){
this.age = age;
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
}
}
log 显示:
我们可以看到打印的地址值是相同的,那肯定是一个对象。
testObjectOne,testObjectTwo 只是引用而已,都指向一个相同的对象 Person。
可以把这种现象叫做引用的复制:
2)下面我们看一下克隆一个对象:
这个时候 Person 类需要继承 Cloneable 实现 clone 接口
package com.example.lum.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Person testObjectOne;
Person testObjectTwo;
testObjectOne = new Person(28,"lu"); //新建 一个对象 one
testObjectTwo = (Person) testObjectOne.clone(); //将 one 克隆Two
System.out.println("``````````````");
System.out.println(testObjectOne);
System.out.println(testObjectTwo);
System.out.println("``````````````");
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
class Person implements Cloneable {
private int age;
private String name ;
public Person(int age,String name){
this.age = age;
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
}
}
log显示:
我们可以看到
4、clone 分为 浅拷贝 和 深拷贝
就像我们的类一样,里面有 变量,age ,name 。
age 是基础数据类型,在clone 时直接 将一个4字节数值拷贝过来,
name 是String 类型,它是一个引用,指向String 对象。那么对它的clone有两种,一种是将引用拷给新的对象,一种是将最它指向的字符串对象clone出来,赋值给新的对象。
这两种方式 一个是浅拷贝,一个是深拷贝
1) 浅拷贝
2)、深拷贝
3)、浅拷贝示例
我们上面代码就是浅拷贝示例,我们比较下拷贝对象里的 name 地址 和 原对象地址是否一样
package com.example.lum.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Person testObjectOne;
Person testObjectTwo;
testObjectOne = new Person(28,"lu"); //新建 一个对象 one
testObjectTwo = (Person) testObjectOne.clone(); //将 one 赋值给 Twos
System.out.println("``````````````");
System.out.println(testObjectOne.getName());
System.out.println(testObjectTwo.getName());
System.out.println((testObjectOne.getName() == testObjectTwo.getName()));
System.out.println("``````````````");
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
class Person implements Cloneable {
private int age;
private String name ;
public Person(int age,String name){
this.age = age;
this.name = name;
}
public int getAge(){
return this.age;
}
public String getName (){
return this.name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Person)super.clone();
}
}
}
打印的 log:
4)、深拷贝的例子
我们在年龄,姓名,之上添加一个灵魂
package com.example.lum.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Person testObjectOne;
Person testObjectTwo;
testObjectOne = new Person(28,"lu",new Soul()); //新建 一个对象 one
testObjectTwo = (Person) testObjectOne.clone(); //将 one 赋值给 Twos
System.out.println("``````````````");
System.out.println(testObjectOne.getName());
System.out.println(testObjectTwo.getName());
System.out.println((testObjectOne.getName() == testObjectTwo.getName()));
System.out.println(testObjectOne.getSoul());
System.out.println(testObjectTwo.getSoul());
System.out.println((testObjectOne.getSoul() == testObjectTwo.getSoul()));
System.out.println("``````````````");
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
class Person implements Cloneable {
private int age;
private String name ;
private Soul soul;
public Person(int age,String name, Soul soul){
this.age = age;
this.name = name;
this.soul = soul;
}
public int getAge(){
return this.age;
}
public String getName (){
return this.name;
}
public Soul getSoul (){
return this.soul;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person person = (Person) super.clone(); // 回调 clone 方法 新建Person 对象
person.soul = (Soul) soul.clone(); //同时 对象 里的 灵魂对象 clone 自身父类
return person;
}
}
//新建灵魂对象 同时 也 添加 Cloneable 接口
class Soul implements Cloneable{
public Soul(){}
@Override
protected Object clone() throws CloneNotSupportedException {
return (Soul)super.clone();
}
}
}
log :
我们可以看到 灵魂的对象他们clone 前后的地址是不一样的。
就是深克隆 ,克隆的对象里的对象也要克隆。