深复制与浅复制的概念
1. 什么是浅复制
浅复制:只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
2. 什么是深复制
深复制:就是复制一个完全不同的对象出来,没有任何关联,只是它们的属性值都是相同的,后续对任何一个的修改或其他操作都不会对另外一个有影响!
深复制与浅复制的应用场景
深复制的应用:1、在日志打印时,打印对象的数据时,对敏感信息脱敏
深复制的实现代码
实现思想:
首先要区分开值复制 和 对象复制,基本数据类型和String类型不需要复制值,直接将值返回,如果为对象 利用newInstance方法 创建一个对象 然后依据是深度复制还是浅复制,再复制对象属性字段,如果属性中有对象属性,再循环递归调用clone方法;
与网上的东西的优势:不用类特殊的实现cloneable 或者 serilizable 接口就可使用,优势在于对于已经成型对象不需要特殊的修改,即可实现复制克隆
/**
* Copyright 2017 by IPS. Floor 3,Universal Industrial Building,
* Tian Yaoqiao Road 1178,Shanghai, P.R. China,200300. All rights reserved.
*
* This software is the confidential and proprietary information of IPS
* ("Confidential Information"). You shall not disclose such
* Confidential Information and shall use it only in accordance with the terms
* of the license agreement you entered into with IPS.
*/
package com.xxx.fpms.common.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @Description: 克隆工具类
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class CloneUtil {
/**
* 复制对象数据
*
* @param value
* 原始对象
* @param level
* 复制深度。小于0为无限深度,即将深入到最基本类型和Object类级别的数据复制;
* 大于0则按照其值复制到指定深度的数据,等于0则直接返回对象本身而不进行任何复制行为。
* @return 返回复制后的对象
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public static Object clone (Object value, int level) throws IllegalAccessException, InstantiationException, InvocationTargetException,
NoSuchMethodException {
if (value == null) {
return null;
}
if (level == 0) {
return value;
}
Class c = value.getClass();
c.isLocalClass();
if (isNeedlessClone(c)) {
return value;
}
level--;
if (value instanceof Collection) {// 复制新的集合
Collection tmp = (Collection) c.newInstance();
for (Object v : (Collection) value) {
tmp.add(clone(v, level));// 深度复制
}
value = tmp;
} else if (c.isArray()) {// 复制新的Array
// 首先判断是否为基本数据类型
if (c.equals(int[].class)) {
int[] old = (int[]) value;
value = (int[]) Arrays.copyOf(old, old.length);
} else if (c.equals(short[].class)) {
short[] old = (short[]) value;
value = (short[]) Arrays.copyOf(old, old.length);
} else if (c.equals(char[].class)) {
char[] old = (char[]) value;
value = (char[]) Arrays.copyOf(old, old.length);
} else if (c.equals(float[].class)) {
float[] old = (float[]) value;
value = (float[]) Arrays.copyOf(old, old.length);
} else if (c.equals(double[].class)) {
double[] old = (double[]) value;
value = (double[]) Arrays.copyOf(old, old.length);
} else if (c.equals(long[].class)) {
long[] old = (long[]) value;
value = (long[]) Arrays.copyOf(old, old.length);
} else if (c.equals(boolean[].class)) {
boolean[] old = (boolean[]) value;
value = (boolean[]) Arrays.copyOf(old, old.length);
} else if (c.equals(byte[].class)) {
byte[] old = (byte[]) value;
value = (byte[]) Arrays.copyOf(old, old.length);
} else {
Object[] old = (Object[]) value;
Object[] tmp = (Object[]) Arrays.copyOf(old, old.length, old.getClass());
for (int i = 0; i < old.length; i++) {
tmp[i] = clone(old[i], level);
}
value = tmp;
}
} else if (value instanceof Map) {// 复制新的MAP
Map tmp = (Map) c.newInstance();
Map org = (Map) value;
for (Object key : org.keySet()) {
tmp.put(key, clone(org.get(key), level));// 深度复制
}
value = tmp;
} else {
Object tmp = null;
tmp = createObject(value);
if (tmp == null) {// 无法创建新实例则返回对象本身,没有克隆
return value;
}
Set<Field> fields = new HashSet<Field>();
while (c != null && !c.equals(Object.class)) {
fields.addAll(Arrays.asList(c.getDeclaredFields()));
c = c.getSuperclass();
}
for (Field field : fields) {
if (!Modifier.isFinal(field.getModifiers())) {// 仅复制非final字段
field.setAccessible(true);
if ("cdate".equalsIgnoreCase(field.getName())) {
continue;
}
field.set(tmp, clone(val, level));// 深度复制
}
}
value = tmp;
}
return value;
}
/**
* 浅表复制对象
*
* @param value
* 原始对象
* @return 复制后的对象,只复制一层
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public static Object clone (Object value) {
try {
return clone(value, 1);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return value;
}
}
/**
* 深度复制对象
*
* @param value
* 原始对象
* @return 复制后的对象
* @throws IllegalAccessException
* @throws InstantiationException
* @throws InvocationTargetException
* @throws NoSuchMethodException
*/
public static Object deepClone (Object value) {
try {
return clone(value, -1);
} catch (Exception e) {
logger.error(e.getMessage(), e);
return value;
}
}
/**
* 无需进行复制的特殊类型数组
*/
static Class[] needlessCloneClasses = new Class[] { String.class, Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class,
Float.class, Double.class, Void.class, Object.class, Class.class };
/**
* 判断该类型对象是否无需复制
*
* @param c
* 指定类型
* @return 如果不需要复制则返回真,否则返回假
*/
private static boolean isNeedlessClone (Class c) {
if (c.isPrimitive()) {// 基本类型
return true;
}
for (Class tmp : needlessCloneClasses) {// 是否在无需复制类型数组里
if (c.equals(tmp)) {
return true;
}
}
return false;
}
/**
* 尝试创建新对象
*
* @param c
* 原始对象
* @return 新的对象
* @throws IllegalAccessException
*/
private static Object createObject (Object value) throws IllegalAccessException {
try {
return value.getClass().newInstance();
} catch (InstantiationException e) {
return null;
} catch (IllegalAccessException e) {
throw e;
}
}
}