频道栏目
首页 > 资讯 > Java > 正文

JAVA 对象的深拷贝代码实例

18-06-08        来源:[db:作者]  
收藏   我要投稿

JAVA 对象的深拷贝代码实例

package com.ctrip.ibu.itinerary.common.util;  
  
import com.google.common.primitives.Primitives;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
import sun.misc.Unsafe;  
  
import java.lang.reflect.Array;  
import java.lang.reflect.Field;  
import java.lang.reflect.Modifier;  
import java.util.IdentityHashMap;  
import java.util.Map;  
  
/** 
 * The utility to deep copy the given object. 
 */  
public final class CopyUtils {  
    private static final Logger log = LoggerFactory.getLogger(CopyUtils.class);  
  
    private CopyUtils() {  
    }  
  
    /** 
     * Deep-copy the given object. 
     * 
     * @param src the source object to be deep-copied. 
     * @param <T> the type of the given object. 
     * @return the deep-copied object. 
     * @throws IllegalAccessException 
     * @throws NoSuchFieldException 
     * @throws InstantiationException 
     */  
    public static <T> T copy(T src) throws IllegalAccessException, NoSuchFieldException, InstantiationException {  
        return doCopy(src, new IdentityHashMap<>());  
    }  
  
    /** 
     * Deep-copy the given object. 
     * 
     * @param src     the source object to be deep-copied. 
     * @param visited the copied object collection. 
     * @param <T>     the type of the given object. 
     * @return the deep-copied object. 
     * @throws IllegalAccessException 
     * @throws NoSuchFieldException 
     * @throws InstantiationException 
     */  
    private static <T> T doCopy(T src, Map<Object, Object> visited) throws IllegalAccessException, NoSuchFieldException, InstantiationException {  
        if (src == null) {  
            return null;  
        }  
        if (src.getClass().isAssignableFrom(String.class)  
                || src.getClass().isEnum()  
                || src.getClass() == Class.class) {  
            return src;  
        }  
        if (visited.containsKey(src)) {  
            return (T) visited.get(src);  
        }  
        if (src.getClass().isArray()) {  
            return copyArray(src, visited);  
        }  
        return copyObject(src, visited);  
    }  
  
    /** 
     * Gets the unsafe object to create a new instance. 
     * 
     * @return the {@link Unsafe} object. 
     * @throws NoSuchFieldException 
     * @throws IllegalAccessException 
     */  
    private static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException {  
        Field f = Unsafe.class.getDeclaredField("theUnsafe");  
        f.setAccessible(true);  
        return (Unsafe) f.get(null);  
    }  
  
    /** 
     * Deep-copy the array object. 
     * 
     * @param src     the given object with array type. 
     * @param visited the copied object collection. 
     * @param <T>     the type of the element in the given array. 
     * @return the deep-copied array object. 
     * @throws IllegalAccessException 
     * @throws NoSuchFieldException 
     * @throws InstantiationException 
     */  
    private static <T> T copyArray(T src, Map<Object, Object> visited) throws IllegalAccessException, NoSuchFieldException, InstantiationException {  
        int length = Array.getLength(src);  
        Object result =  
                Array.newInstance(  
                        src.getClass().getComponentType(),  
                        Array.getLength(src));  
        visited.put(src, result);  
        for (int i = 0; i < length; i++) {  
            Array.set(result, i, doCopy(Array.get(src, i), visited));  
        }  
        return (T) result;  
    }  
  
    /** 
     * Checks if the given field with the given modifier. 
     * 
     * @param field    the given field to check. 
     * @param modifier the modifier of the given field. 
     * @return {@code true} if the field has the given modifier, otherwise {@code false}. 
     */  
    private static boolean hasModifier(Field field, int modifier) {  
        return (field.getModifiers() & modifier) != 0;  
    }  
  
    /** 
     * Deep-copy the given object with a new instance. 
     * 
     * @param src     the given object to be deep-copied. 
     * @param visited the copied object collection. 
     * @param <T>     the type of the given object. 
     * @return the deep-copied object instance. 
     * @throws NoSuchFieldException 
     * @throws IllegalAccessException 
     * @throws InstantiationException 
     */  
    private static <T> T copyObject(T src, Map<Object, Object> visited) throws NoSuchFieldException, IllegalAccessException, InstantiationException {  
        Object result = getUnsafe().allocateInstance(src.getClass());  
        visited.put(src, result);  
        Class<?> clazz = src.getClass();  
        do {  
            Field[] fields = clazz.getDeclaredFields();  
            for (Field field : fields) {  
                // if the field is static or final we won't do anything with it  
                if (hasModifier(field, Modifier.STATIC) || hasModifier(field, Modifier.FINAL)) {  
                    continue;  
                }  
                field.setAccessible(true);  
                // if it's primitive, we just set it's value to our new instance  
                // otherwise we recursively copy it's value  
                if (Primitives.unwrap(field.getType()).isPrimitive()) {  
                    field.set(result, field.get(src));  
                } else {  
                    field.set(result, doCopy(field.get(src), visited));  
                }  
            }  
            clazz = clazz.getSuperclass();  
        } while (clazz != null);  
        return (T) result;  
    }  
  
    /** 
     * Deep-copy the given object. 
     * 
     * @param source the original object. 
     * @return the deep-copied object instance. 
     */  
    public static <T> T deepCopy(T source) {  
        try {  
            return CopyUtils.copy(source);  
        } catch (Exception e) {  
            log.error("Failed to deep-copy the given object.", e);  
            return null;  
        }  
    }  
}  

这个工具代码可以保证复杂结构的对象深拷贝的多线程安全和避免调用对象的构造器,同时根据需要可以决定是否过滤掉static和final修饰的属性和值。感兴趣的朋友可以研究研究。

相关TAG标签
上一篇:c#中的查看成绩的简单代码实现
下一篇:设计模式学习之命令模式实例讲解
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站