gu.sql2java.utils.DeepCloneUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sql2java-base Show documentation
Show all versions of sql2java-base Show documentation
sql2java common class package
package gu.sql2java.utils;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.google.common.base.Throwables;
import com.google.common.primitives.Primitives;
import gu.sql2java.Constant;
import static java.lang.reflect.Modifier.FINAL;
import static java.lang.reflect.Modifier.STATIC;
/**
* 深度对象克隆工具,copy from common-java
* @author guyadong
* @since 3.24.0
*/
public class DeepCloneUtils implements Constant{
/**
* (深度克隆)复制数据对象的所有字段,输入参数为{@code null}返回{@code null}
* 基本数据类型(primitive,String)不做复制,其他类型字段执行{@link #deepClone(Object) }方法深度克隆
* @param input
* @param ifVolatile 定义对 volatile 字段的处理方式:
*
* - 1 -- 字段设置为{@code null}
* - 2 -- 执行克隆
* - 其他 -- 跳过此字段
*
* @return always input
* @see #deepClone(Object)
*/
public static T cloneFields(T input, int ifVolatile){
if(noClone(input)){
/** 基本类型不需要复制 */
return input;
}
for(Class> clazz=input.getClass();null != clazz && !Object.class.equals(clazz);clazz = clazz.getSuperclass()) {
for(Field field:clazz.getDeclaredFields()) {
try {
if(((field.getModifiers() & (STATIC+FINAL)) == 0 && !noClone(field.getType()))
|| FIELD_MODIFIED.equals(field.getName())
|| FIELD_INITIALIZED.equals(field.getName())) {
field.setAccessible(true);
if(!Modifier.isVolatile(field.getModifiers())) {
field.set(input, deepClone(field.get(input)));
}else if(1 == ifVolatile) {
field.set(input, null);
}else if(2 == ifVolatile) {
field.set(input, deepClone(field.get(input)));
}
}
} catch (IllegalArgumentException | IllegalAccessException e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
}
return input;
}
/**
* (深度克隆)对数据对象的所有字段执行深度复制,输入参数为{@code null}返回{@code null}
* @see #cloneFields(Object, int)
*/
public static T cloneFields(T input){
return cloneFields(input,2);
}
/**
* [递归]复制数据对象(深度克隆),输入参数为{@code null}返回{@code null}
* 基本数据类型(primitive,String)不做复制,原样返回,
* 实现 {@link Cloneable} 接口的对象执行 clone 方法,
* {@link Map}和{@link Collection}接口实现如果有默认构造方法执行{@code putAll,addAll}方法完成对象复制,
* 如果对象类型有复制构造方法,调用复制构造方法完成对象复制,
* 实现 {@link Serializable}接口的对象基于对象的序列化反序列化实现对象复制
* @param input
*/
@SuppressWarnings("unchecked")
public static T deepClone(T input){
if(noClone(input)){
/** 基本类型不需要复制 */
return input;
}
T cloned;
if(input instanceof Collection){
if(input != (cloned = tryConstructContainer(input,Collection.class))){
return cloned;
}
}
if (input instanceof Map) {
if(input != (cloned = tryConstructContainer(input,Map.class))){
return cloned;
}
}
if(input instanceof Cloneable){
if(input.getClass().isArray()){
Class> componentType = input.getClass().getComponentType();
int length = Array.getLength(input);
cloned = (T) Array.newInstance(componentType, length);
System.arraycopy(input, 0, cloned, 0, length);
if(!noClone(componentType)) {
for(int i=0,end_i=Array.getLength(cloned);iT callClone(T input) {
try {
return (T) input.getClass().getMethod("clone").invoke(input);
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
private static boolean noClone(Object object){
if(null == object){
return true;
}
return noClone(object.getClass());
}
private static boolean noClone(Class> clazz){
if(Primitives.unwrap(clazz).isPrimitive()){
return true;
}
if(String.class.equals(clazz)){
return true;
}
return false;
}
/**
* {@link Map},{@link Collection}类型,如果有默认构造方法使用{@code putAll,addAll}方法完成对象复制
* @param input
* @param targetType
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private static T tryConstructContainer(T input,Class>targetType){
if(targetType.isInstance(input)){
try{
Object output ;
if(input instanceof Map || input instanceof Collection){
output = input.getClass().getConstructor().newInstance();
if(output instanceof Map){
Set entrySet = ((Map)input).entrySet();
for(Entry entry:entrySet) {
((Map)output).put(entry.getKey(), deepClone(entry.getValue()));
}
return (T) output;
}else if(output instanceof Collection){
for(Object element:(Collection)input) {
((Collection)output).add(deepClone(element));
}
return (T) output;
}
}
} catch (Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
return input;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy