深拷贝与浅拷贝的区别
浅拷贝只是拷贝了源对象的地址,所以当源对象发生改变时,拷贝的对象的值也会对应发生改变。 深拷贝则是拷贝了源对象的所有值,而不是地址,所以深拷贝对象中的值不会随着源对象中的值的改变而改变。
浅拷贝只是拷贝了源对象的地址,所以当源对象发生改变时,拷贝的对象的值也会对应发生改变!!!这块儿要注意,有坑!
发生的场景
当如果要拷贝一个A对象,而A对象中又有一个B对象,那么如果对A拷贝的时候,重新拷贝出来一个A1对象并且重新分配内存地址, 但是对于A中的B对象,仅仅只是把A1中拷贝出来的B1对象的引用指向原来的B对象而已, 并没有把拷贝的B1对象也重新进行分配一个新的内存地址。这就是浅拷贝。 而深拷贝就是在第1的基础上,不仅重新给A1对象分配了新的内存地址,而且还给A1中的B1也重新进行分配了新的内存地址, 而不只是仅仅把原本的B的引用给B1。这就是深拷贝。
最基本的实现实现
如果要深拷贝一个对象,那么这个对象必须要实现 Cloneable 接口,实现 重写clone()方法, 并且在 clone 方法内部,把该对象引用的其他对象也要 clone 一份, 这就要求这个被引用的对象必须也要实现Cloneable 接口并且实现 clone 方法
利用反射机制实现
public static void copy(Object source, Object dest) throws Exception {
Class destClz = dest.getClass();
// 获取目标的所有成员
Field[] destFields = destClz.getDeclaredFields();
Object value;
for (Field field : destFields) { // 遍历所有的成员,并赋值
// 获取value值
value = getVal(field.getName(), source);
field.setAccessible(true);
field.set(dest, value);
}
}
private static Object getVal(String name, Object obj) throws Exception {
try {
// 优先获取obj中同名的成员变量
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException e) {
// 表示没有同名的变量
}
// 获取对应的 getXxx() 或者 isXxx() 方法
name = name.substring(0, 1).toUpperCase() + name.substring(1);
String methodName = "get" + name;
String methodName2 = "is" + name;
Method[] methods = obj.getClass().getMethods();
for (Method method : methods) {
// 只获取无参的方法
if (method.getParameterCount() > 0) {
continue;
}
if (method.getName().equals(methodName)
|| method.getName().equals(methodName2)) {
return method.invoke(obj);
}
}
return null;
}
直接上BeanUtil工具类型
package com.bboss.common.util;
import com.github.dozermapper.core.DozerBeanMapperBuilder;
import com.github.dozermapper.core.Mapper;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.core.Converter;
import org.springframework.util.ObjectUtils;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
public class BeanUtil {
/*
* 创建默认的DozerBeanMapper
*/
private static Mapper beanMapper = DozerBeanMapperBuilder.buildDefault();
/*
* BeanCopier的类型缓存map
*/
private static final ConcurrentHashMap<String, SoftReference<BeanCopier>> BEAN_COPIER_CACHE = new ConcurrentHashMap<>();
/**
* @description 生成key
* @param srcClazz 源文件的class
* @param tgtClazz 目标文件的class
* @return string
* @author yanb
* @date 2020/8/01
*/
private static String generateKey(Class<?> srcClazz, Class<?> tgtClazz) {
StringBuilder sb=new StringBuilder(srcClazz.getName()).append(":").append(tgtClazz.getName());
return sb.toString().intern();
}
/**
* bean对象(属性)拷贝
* 浅拷贝,高性能
* @param source 源对象
* @param target 目标对象
* @descriptio BeanCopier的copy
* @author yanb
* @date 2020/8/01
*/
public static void copy(Object source, Object target) {
copy(source, target, null);
}
/**
* 支持自定义converter的拷贝方法
* 浅拷贝,高性能
*/
public static void copy(Object source, Object target, Converter converter) {
if (Objects.isNull(source) || Objects.isNull(target)) {
return;
}
String key = generateKey(source.getClass(), target.getClass());
BeanCopier beanCopier;
if (Objects.isNull(BEAN_COPIER_CACHE.get(key))
|| Objects.isNull(beanCopier = BEAN_COPIER_CACHE.get(key).get())) {
synchronized (key) {
if (Objects.isNull(BEAN_COPIER_CACHE.get(key))
|| Objects.isNull(beanCopier = BEAN_COPIER_CACHE.get(key).get())) {
beanCopier = BeanCopier.create(source.getClass(), target.getClass(), Objects.nonNull(converter));
BEAN_COPIER_CACHE.put(key, new SoftReference<>(beanCopier));
}
}
}
beanCopier.copy(source, target, converter);
}
/* ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ 上面是浅拷贝方法 ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ */
/* ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● 华丽的分割线 ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● ●▂● */
/* ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ 下面是深拷贝方法 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ */
/**
* List拷贝,直接返回list对象
* 深拷贝
* @param source 源对象
* @param destinationClass 目标类型
* @return java.util.List<U>
* @author yanb
* @date 2020/8/01
*/
public static <T, U> List<U> mapList(final List<T> source, final Class<U> destinationClass) {
if (Objects.isNull(source) || Objects.isNull(destinationClass)) {
return null;
}
final List<U> dest = new ArrayList<U>();
for (T element : source) {
dest.add(beanMapper.map(element, destinationClass));
}
return dest;
}
/**
* Collection拷贝,直接返回Collection对象
* 深拷贝
* @param source 源对象
* @param destinationClass 目标类型
* @return java.util.List<U>
* @author yanb
* @date 2020/8/01
*/
public static <T, U> Collection<U> mapCollection(final Collection<T> source, final Class<U> destinationClass) {
if (Objects.isNull(source)||Objects.isNull(destinationClass)) {
return null;
}
final Collection<U> dest = new ArrayList<>();
for (T element : source) {
dest.add(beanMapper.map(element, destinationClass));
}
return dest;
}
/**
* 单个对象的 深拷贝
* 生成新的对象
* @param source 源对象
* @param destinationClass 目标类型
* @return U
* @author yanb
* @date 2021/3/17
*/
public static <T, U> U deepCopy(final T source, Class<U> destinationClass) {
if (Objects.isNull(source) || Objects.isNull(destinationClass)){
return null;
}
return beanMapper.map(source, destinationClass);
}
/**
* 单个对象的 深拷贝
* @param source 源对象
* @param target 目标对象
* @return void
* @author yanb
* @date 2021/3/17
*/
public static <U> void deepCopy(Object source, Object target) {
if (Objects.isNull(source) || Objects.isNull(target)) {
return;
}
beanMapper.map(source, target);
}
public static boolean allFieldIsNULL(Object o) {
try {
Field[] var1 = o.getClass().getDeclaredFields();
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
Field field = var1[var3];
field.setAccessible(true);
Object object = field.get(o);
if (object instanceof CharSequence) {
if (!ObjectUtils.isEmpty(object)) {
return false;
}
} else if (null != object) {
return false;
}
}
} catch (Exception var6) {
}
return true;
}
}
直接调用上面工具类中的mapList
List<CustBlack> custBlacksCopy = BeanUtil.mapList(custBlacks,CustBlack.class);