Java中对象的传递引用、浅拷贝、深拷贝之间区别
What are they?
传递引用: 即两个或多个对象名称指向同一段使用new关键字开辟的地址空间,它们都可以对此地址空间内的对象进行操作,即两个对象是相等的。
如:
Sheep sheep = new Sheep("tom",1,"white"); Sheep sheep1 = sheep;
演示图如下:
浅拷贝: 即原类对象需实现Cloneable接口,通过调用已有对象的clone()方法重新开辟一段内存空间建立对象,但是,对于对象内的引用数据类型,不进行拷贝,只是将新的对象内的引用数据类型也指向原本的地址空间,实现了两个对象的不等。
如(sheep对象内的sheepfriends对象也为Sheep类):
Sheep sheep = new Sheep("tom",1,"white"); sheep.sheepFriends = new Sheep("Jerry",2,"black"); Sheep sheep1 = (Sheep) sheep.clone();
演示图如下:
深拷贝: 也是原类对象需实现Cloneable接口,并且覆写clone()方法实现对引用数据类型的拷贝功能,实现开辟所有数据类型所需的地址空间,从而实现深拷贝,两个对象完全不等。
如:此时的clone方法已经覆写,下面会有具体覆写过程哦!
Sheep sheep = new Sheep("tom",1,"white"); sheep.sheepFriends = new Sheep("Jerry",2,"black"); Sheep sheep1 = (Sheep) sheep.clone();
演示图如下:
那么它们具体怎样实现和使用呢,让我们通过具体的一些案例来演示一下吧,嘻嘻~
具体案例演示
对象的引用传递
Sheep类
package com.design_patterns.prototype.instance;
public class Sheep {
private String name;
private int age;
private String color;
public Sheep(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
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 String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
}
测试类
package com.design_patterns.prototype.instance;
public class Client {
public static void main(String[] args) {
Sheep sheep = new Sheep("tom",1,"white");
Sheep sheep1 = sheep;
System.out.println(sheep + "\n" + sheep.hashCode() + "\n");
System.out.println(sheep1 + "\n" + sheep1.hashCode() + "\n");
System.out.println("这两个对象是否相等?" + (sheep == sheep1));
}
}
运行结果
Sheep{
name='tom', age=1, color='white'}
1163157884
Sheep{
name='tom', age=1, color='white'}
1163157884
这两个对象是否相等?true
对象的浅拷贝
Sheep类
package com.design_patterns.prototype.improve;
public class Sheep implements Cloneable {
private String name;
private int age;
private String color;
public Sheep sheepFriends;
public Sheep(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
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 String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
/**
* 克隆该实例,使用默认的clone()方法完成
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep sheep = null;
sheep = (Sheep)super.clone();
return sheep;
}
}
测试类
package com.design_patterns.prototype.improve;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep = new Sheep("tom",1,"white");
sheep.sheepFriends = new Sheep("Jerry",2,"black");
Sheep sheep1 = (Sheep) sheep.clone();
System.out.println("sheep---->" + sheep + "\nhashcode---->" + sheep.hashCode() + "\n"
+ sheep.sheepFriends.hashCode() + "\n" + sheep.sheepFriends + "\n");
System.out.println("sheep1---->" + sheep1 + "\nhashcode---->" + sheep1.hashCode() + "\n"
+ sheep1.sheepFriends.hashCode() + "\n" + sheep1.sheepFriends + "\n");
sheep.sheepFriends.setName("Jerry Hello");
System.out.println("这两个对象是否相等?" + (sheep == sheep1));
System.out.println("它们的属性对象是否为同一个对象?" + (sheep.sheepFriends == sheep1.sheepFriends));
}
}
运行结果
sheep---->Sheep{
name='tom', age=1, color='white'}
hashcode---->1163157884
1956725890
Sheep{
name='Jerry', age=2, color='black'}
sheep1---->Sheep{
name='tom', age=1, color='white'}
hashcode---->356573597
1956725890
Sheep{
name='Jerry', age=2, color='black'}
这两个对象是否相等?false
它们的属性对象是否为同一个对象?true
对象的深拷贝(通过覆写clone()方法实现)
Sheep类
package com.design_patterns.prototype.deepclone;
import java.io.*;
public class Sheep implements Cloneable, Serializable {
private String name;
private int age;
private String color;
public Sheep sheepFriends;
public Sheep(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
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 String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
/**
* 覆写clone()方法
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
Object deep = null;
//这里对基本数据类型属性的克隆
deep = super.clone();
//对应用数据类型的属性进行单独处理
Sheep sheep = (Sheep)deep;
if(this.sheepFriends != null){
//若引用数据类型不为空,也进行拷贝复制
sheep.sheepFriends = (Sheep) this.sheepFriends.clone();
}
return sheep;
}
/**
* 也是深拷贝方法,通过对对象对象实现序列化的操作完成对象的全部拷贝工作
* 通常建议用此种方法实现对象的深拷贝,此类需要实现Serializable接口
* @return
*/
public Object deepClone(){
Sheep sheep = null;
//创建流对象
ByteArrayOutputStream byteArrayOutputStream = null; //定义内存输出流
ObjectOutputStream objectOutputStream = null; //定义对象输出流
ByteArrayInputStream byteArrayInputStream = null; //定义内存输入流
ObjectInputStream objectInputStream = null; //定义对象输入流
try{
byteArrayOutputStream = new ByteArrayOutputStream(); //实例化内存输出流
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); //实例化对象输出流,将对象输出到内存中
objectOutputStream.writeObject(this); //将对象写入内存
byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); //实例化内存输入流
objectInputStream = new ObjectInputStream(byteArrayInputStream); //实例化对象输入流
sheep = (Sheep)objectInputStream.readObject(); //将此对象再读取出来,写入sheep对象中
objectInputStream.close();
byteArrayInputStream.close();
objectOutputStream.close();
byteArrayOutputStream.close(); //关闭流对象
}catch (Exception e) {
e.printStackTrace();
}
return sheep; //返回深拷贝的对象
}
}
测试类
package com.design_patterns.prototype.deepclone;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep = new Sheep("tom",1,"white");
sheep.sheepFriends = new Sheep("Jerry",2,"black");
Sheep sheep1 = (Sheep) sheep.clone(); //采用引用数据也克隆的方式
Sheep sheep2 = (Sheep) sheep.deepClone(); //采用对象序列化的操作实现深拷贝
System.out.println("sheep---->" + sheep + "\nhashcode---->" + sheep.hashCode() + "\n"
+ sheep.sheepFriends.hashCode() + "\n" + sheep.sheepFriends + "\n");
System.out.println("sheep1---->" + sheep1 + "\nhashcode---->" + sheep1.hashCode() + "\n"
+ sheep1.sheepFriends.hashCode() + "\n" + sheep1.sheepFriends + "\n");
System.out.println("sheep2---->" + sheep2 + "\nhashcode---->" + sheep2.hashCode() + "\n"
+ sheep2.sheepFriends.hashCode() + "\n" + sheep2.sheepFriends + "\n");
System.out.println("这三个对象相同嘛(sheep、sheep1、sheep2):"+ "\n" + (sheep == sheep1)+ "\n" + (sheep == sheep2)
+ "\n" +(sheep1 == sheep2) + "\n");
System.out.println("这三个对象的引用数据类型相同嘛:" + "\n" + (sheep.sheepFriends == sheep1.sheepFriends) + "\n" +
(sheep.sheepFriends == sheep2.sheepFriends) + "\n"+ (sheep1.sheepFriends == sheep2.sheepFriends) + "\n");
}
}
运行结果
sheep---->Sheep{
name='tom', age=1, color='white'}
hashcode---->325040804
312714112
Sheep{
name='Jerry', age=2, color='black'}
sheep1---->Sheep{
name='tom', age=1, color='white'}
hashcode---->931919113
1607521710
Sheep{
name='Jerry', age=2, color='black'}
sheep2---->Sheep{
name='tom', age=1, color='white'}
hashcode---->764977973
381259350
Sheep{
name='Jerry', age=2, color='black'}
这三个对象相同嘛(sheep、sheep1、sheep2):
false
false
false
这三个对象的引用数据类型相同嘛:
false
false
false
总结
到此,这就是Java对象的引用传递、对象浅拷贝、对象深拷贝的全部区别,如果感觉这篇文章写的还不错(代码的冗余有点多,嘻嘻),帮忙点个赞哦,谢谢小伙伴们的支持~