浅克隆:顾名思义就是很表面的很表层的克隆,比如我们要克隆User对象,浅克隆只克隆他自身以及他包含的所有对象的引用地址。
深克隆:就是非浅克隆。克隆除自身以外所有的对象,包括自身所包含的所有对象实例。至于深克隆的层次,由具体的需求决定,也有“N层克隆”一说。
浅克隆:
1、使用Cloneable接口实现,步骤如下:
a. 让该类实现Java.lang.Cloneable接口;
b. 重写(override)Object类的clone()方法。
深克隆:
方法1:通过Cloneable接口实现,但这里必须类中所有的非基本类型域都实现Cloneable接口,才能实现深克隆,所以此方法不通用
方法2:通过串行化方式实现(克隆对象必须实现Serializable接口)
把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做 “解冻”或者“回鲜(depicking)”过程。
应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。
在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public abstract class BeanUtil {
@SuppressWarnings("unchecked")
public static <T> T cloneTo(T src) throws RuntimeException {
ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
ObjectOutputStream out = null;
ObjectInputStream in = null;
T dist = null;
try {
out = new ObjectOutputStream(memoryBuffer);
out.writeObject(src);
out.flush();
in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));
dist = (T) in.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (out != null)
try {
out.close();
out = null;
} catch (IOException e) {
throw new RuntimeException(e);
}
if (in != null)
try {
in.close();
in = null;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return dist;
}
}
方法3:通过反射的方式实现(克隆对象必须是可序列化的)
即依次遍历克隆对象中的所有域,直至全部域均为基本类型为止
package com.example.xiaowang.clonetest;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by xiaowang on 17/3/9.
*/
public class CloneUtil {
/**
* 返回对象的所以属性 包括继承至父类的属性
*
* @param o
* @return
*/
private static List<Field> getAllFieads(Object o) {
List<Field> fields = new ArrayList<Field>();
if (null == o) {
return fields;
}
Class<?> type = o.getClass();
do {
for (Field f : type.getDeclaredFields()) {
fields.add(f);
}
type = type.getSuperclass();
} while (null != type);
return fields;
}
/**
* 基于效率的考虑不需要进行深度复制的类型:包括基本类型和包装类
*
* @param o
* @return
*/
public static boolean isSimpleObject(Object o) {
Class<?> type = o.getClass();
if (type.isPrimitive()) { // 基本类型
return true;
}
// 不可更改的变量类型 如 String,Long
if (type.equals(String.class)) {
return true;
}
if (type.equals(Long.class)) {
return true;
}
if (type.equals(Boolean.class)) {
return true;
}
if (type.equals(Short.class)) {
return true;
}
if (type.equals(Integer.class)) {
return true;
}
if (type.equals(Character.class)) {
return true;
}
if (type.equals(Float.class)) {
return true;
}
if (type.equals(Double.class)) {
return true;
}
if (type.equals(Byte.class)) {
return true;
}
return false;
}
/**
* 没有对cloneAble接口进行限制
*
* @param o
* @return
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static Object cloneObject(Object o) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
if (null == o) {
return null;
}
// 使用Map保存原对象和副本对象之间的结构,防止被多次引用的对象重复重建
Map<Object, Object> map = new HashMap<Object, Object>();
return cloneObject(o, map);
}
private static Object cloneObject(Object o, Map<Object, Object> map)
throws IllegalArgumentException, IllegalAccessException,
InstantiationException {
if (null == o) {
return null;
}
Object newInstance = null;
newInstance = map.get(o);
if (null != newInstance) {
return newInstance;
}
if (isSimpleObject(o))
return o;
// 数组类型
if (o.getClass().isArray()) {
return cloneArray(o, map);
}
Class<?> type = o.getClass();
newInstance = type.newInstance();
map.put(o, newInstance);
cloneFields(o, newInstance, map);
return newInstance;
}
/**
* 克隆数组对象
*
* @param o
* @param map
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
private static Object cloneArray(Object o, Map<Object, Object> map) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
if (null == o) {
return null;
}
if (!o.getClass().isArray()) {
return cloneObject(o, map);
}
int len = Array.getLength(o);
Object array = Array.newInstance(o.getClass().getComponentType(), len);
map.put(o, array);
for (int i = 0; i < len; i++) {
Array.set(array, i, cloneObject(Array.get(o, i), map));
}
return array;
}
/**
* 对于final类型的变量 如果其为引用, 则尽管引用的值不需要更改,但引用对象的数据还是需要填充的
*
* @param object
* @param newObject
* @param map
* @return
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
*/
private static void cloneFinalObject(Object object, Object newObject, Map<Object, Object> map) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
if (object == null || newObject == null || object == newObject || !newObject.getClass().equals(newObject.getClass())) {
return;
}
// 对于final类型的变量
if (null != map.get(newObject)) {
return;
}
map.put(newObject, newObject);
cloneFields(object, newObject, map);
return;
}
private static void cloneFields(Object object, Object newObject,
Map<Object, Object> map) throws SecurityException,
IllegalArgumentException, IllegalAccessException,
InstantiationException {
if (null == object || null == newObject) {
return;
}
List<Field> fields = getAllFieads(object);
for (Field f : fields) {
// 静态变量过滤掉 或者final的变量
if (Modifier.isStatic(f.getModifiers()))
continue;
// 常量
if (Modifier.isFinal(f.getModifiers())) {
cloneFinalObject(f.get(object), f.get(newObject), map);
} else {
f.setAccessible(true);
f.set(newObject, cloneObject(f.get(object), map));
}
}
}
}
方法4:通过Json转换的方式(克隆对象必须实现Serializable接口)
Bean bean1 = new Bean();
Bean bean2 = new Gson().fromJson(new Gson().toJson(bean1), new TypeToken<Bean>(){}.getType());