一、引用拷贝

java 零拷贝技术 Mmap java浅拷贝方法_System

/**
* 引用拷贝</br>
*/
User u1 = new User();
User u2 = u1;
// 引用拷贝,两个引用指向同一个对象(打印的地址值一样)
System.out.println(u1);
System.out.println(u2);

二、浅拷贝

浅拷贝就是使用Object的Clone()方法。创建一个新对象,然后将当前对象的非静态字段复制到新对象,如果字段是基本数据类型的,那么对该字段执行复制;如果字段是引用类型的话,则复制引用但不复制引用的对象。

java 零拷贝技术 Mmap java浅拷贝方法_深拷贝_02

package com.felix.learn.clone;
 
import lombok.Data;
 
/**
* Title: 浅拷贝
* Description: ShallowCopy
*/
public class ShallowCopy {
 
public static void main(String[] args) throws CloneNotSupportedException {
/**
* 浅拷贝
*/
Apple a1 = new Apple();
a1.setPrice(10);
Fruit f1 = new Fruit();
f1.setColor("red");
f1.setApple(a1);
Fruit f2 = (Fruit) f1.clone();
// 修改Apple对象
a1.setPrice(20);
System.out.println("f1:" + f1.getApple().getPrice());
System.out.println("f2:" + f2.getApple().getPrice());
 
}
}
 
/**
* 水果类
* 调用clone()方法的对象要实现Cloneable接口,重写clone()方法
*/
@Data
class Fruit implements Cloneable {
private String color;
private Apple apple;
 
@Override
public Object clone() throws CloneNotSupportedException {
Object object = super.clone();
return object;
}
}
 
/**
* 苹果类
*/
@Data
class Apple {
private double price;
}

三、深拷贝

clone()是Object类中的方法,该方法的基本规则如下:

1.基本数据类型

如果变量是基本数据类型,则拷贝其值,比如int、float等。

2.对象

如果变量是一个实例对象,则拷贝其地址引用,也就是说此时新对象与原来对象是公用该实例变量。

3.String字符串

若变量为String字符串,则拷贝其地址引用。但是在修改时,它会从字符串池中重新生成一个新的字符串,原有字符串对象保持不变。

我们通过重写clone()方法来实现深拷贝;

java 零拷贝技术 Mmap java浅拷贝方法_System_03

package com.felix.learn.clone;
 
import lombok.Data;
 
/**
* Title: 深拷贝
* Description: ShallowCopy
*/
public class DeepCopy {
 
public static void main(String[] args) throws CloneNotSupportedException {
/**
* 深拷贝
*/
AppleA a1 = new AppleA();
a1.setPrice(10);
FruitA f1 = new FruitA();
f1.setColor("red");
f1.setApple(a1);
FruitA f2 = (FruitA) f1.clone();
a1.setPrice(20);
System.out.println("f1:" + f1.getApple().getPrice());
System.out.println("f2:" + f2.getApple().getPrice());
}
}
 
/**
* 水果类</br>
* 调用clone()方法的对象要实现Cloneable接口,重写clone()方法
*/
@Data
class FruitA implements Cloneable {
private String color;
private AppleA apple;
 
@Override
public Object clone() throws CloneNotSupportedException {
// 浅拷贝的写法
// Object object = super.clone();
// return object;
 
// 深拷贝的实现
FruitA fruit = (FruitA) super.clone();
fruit.setApple((AppleA) fruit.getApple().clone());
return fruit;
}
}
 
/**
* 苹果类
*/
@Data
class AppleA implements Cloneable {
private double price;
 
@Override
protected Object clone() throws CloneNotSupportedException {
Object object = super.clone();
return object;
}
}

四、字节流序列化实现深拷贝

对于上面实现深拷贝的方法,若我们系统中存在大量的对象需要拷贝,那我们针对每一个类都需要写一个clone()方法,并将还需要进行深拷贝,新建大量的对象,这个工程是非常大的,这里我们可以利用序列化来实现对象的深拷贝。

package com.felix.learn.clone;
 
import lombok.Data;
 
import java.io.*;
 
/**
* Title: CloneUtils<br>
* Description: CloneUtils<br>
* Company:韦博英语在线教育部</br>
* CreateDate:2018年10月26日 17:51
*
* @author felix.yl
*/
public class CloneUtils {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj) {
T cloneObj = null;
try {
// 写入字节流
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(obj);
obs.close();
 
// 分配内存,写入原始对象,生成新对象
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(ios);
// 返回生成的新对象
cloneObj = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
 
public static void main(String[] args) {
/**
* 字节流序列化实现深拷贝
*/
AppleB a1 = new AppleB();
a1.setPrice(10);
FruitB f1 = new FruitB();
f1.setColor("red");
f1.setApple(a1);
FruitB f2 = CloneUtils.clone(f1);
a1.setPrice(20);
System.out.println("f1:" + f1.getApple().getPrice());
System.out.println("f2:" + f2.getApple().getPrice());
}
}
 
/**
* 水果类</br>
* 调用clone()方法的对象要实现Cloneable接口,重写clone()方法
*/
@Data
class FruitB implements Serializable {
private String color;
private AppleB apple;
}
 
/**
* 苹果类
*/
@Data
class AppleB implements Serializable {
private double price;
}