All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.azbh111.utils.java.reflect.ObjectUtils Maven / Gradle / Ivy

The newest version!
package com.github.azbh111.utils.java.reflect;

import com.github.azbh111.utils.java.exception.ExceptionUtils;
import com.github.azbh111.utils.java.reflect.model.ClassCopyDesc;
import com.github.azbh111.utils.java.reflect.model.UnsafeField;
import com.github.azbh111.utils.java.unsafe.UnsafeUtils;

import java.io.Console;
import java.lang.annotation.Annotation;
import java.lang.instrument.ClassDefinition;
import java.lang.reflect.*;
import java.net.URI;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;

/**
 * @author zhengyongpan
 * @date 2018/7/19 下午2:06
 */
public class ObjectUtils {

    // 缓存一些不可变的类
    private static final Set unmodifiedClass = ConcurrentHashMap.newKeySet();
    private static final Set unmodifiedClassForDeepCopy = ConcurrentHashMap.newKeySet();
    private static final Set unmodifiedClassForShallowCopy = ConcurrentHashMap.newKeySet();

    private static final Map> unsafeFieldMap = new ConcurrentHashMap<>();

    static {
        registerUnmodifiedClass(String.class);
        registerUnmodifiedClass(Boolean.class);
        registerUnmodifiedClass(Character.class);
        registerUnmodifiedClass(Byte.class);
        registerUnmodifiedClass(Short.class);
        registerUnmodifiedClass(Integer.class);
        registerUnmodifiedClass(Long.class);
        registerUnmodifiedClass(Float.class);
        registerUnmodifiedClass(Double.class);
        registerUnmodifiedClass(UUID.class);
        registerUnmodifiedClass(URL.class);
        registerUnmodifiedClass(URI.class);

        registerUnmodifiedClass(Class.class);
        registerUnmodifiedClass(Field.class);
        registerUnmodifiedClass(Constructor.class);
        registerUnmodifiedClass(Method.class);
        registerUnmodifiedClass(Parameter.class);

        registerUnmodifiedClass(ClassDefinition.class);

        registerUnmodifiedClass(Console.class);

        // ThreadLocal中只有一个hashCode变量,这个值是作为key来取值的,如果进行深拷贝,hashCode不变,应该不影响使用(未测试),所以直接当成不可变类处理
        registerUnmodifiedClass(ThreadLocal.class);
    }


    /**
     * 将对象字段名字和值,组装成map
     *
     * @param object
     * @return
     */
    public static Map toMap(Object object) {
        return toMap(object, field -> true);
    }

    /**
     * 将对象字段名字和值,组装成map
     *
     * @param object
     * @return
     */
    public static Map toMap(Object object, Predicate filter) {
        Map map = new HashMap<>();
        if (object == null) {
            return map;
        }
        for (Field field : ReflectUtils.getAllFields(object.getClass(), filter)) {
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            try {
                map.put(field.getName(), field.get(object));
            } catch (IllegalAccessException e) {
                ExceptionUtils.throwException(e);
            }
        }
        return map;
    }

    /**
     * 注册不可变的类
     * 不可变的类的对象在深拷贝和浅拷贝时,都是直接返回对象自身
     *
     * @param clazz
     */
    public static void registerUnmodifiedClass(Class clazz) {
        unmodifiedClassForDeepCopy.add(clazz);
        unmodifiedClassForShallowCopy.add(clazz);
    }

    /**
     * 判断一个对象是否是枚举
     *
     * @param o
     * @return
     */
    public static boolean isEnum(Object o) {
        // Enum不可以被class继承,所以可以直接这样判断
        return o instanceof Enum;
    }

    /**
     * 判断一个对象是否是注解
     *
     * @param o
     * @return
     */
    public static boolean isAnnotation(Object o) {
        // 注解对象实现了Annotation,继承了Proxy,而Proxy的superClass是Object
        if (o instanceof Annotation
                && o instanceof Proxy
                && o.getClass().getSuperclass() != null
                && o.getClass().getSuperclass().getSuperclass() == Object.class) {
            return true;
        }
        return false;
    }

    /**
     * 深拷贝任意对象
     *
     * @param s
     * @param 
     * @return
     * @throws Throwable
     */
    public static  T deepCopy(T s) throws InstantiationException {
        return deepCopy(new IdentityHashMap<>(), s);
    }

    /**
     * 深拷贝任意对象
     *
     * @param cache 用来处理循环引用 key:拷贝前对象,value:对象
     * @param s
     * @param 
     * @return
     * @throws InstantiationException
     */
    private static  T deepCopy(Map cache, T s) throws InstantiationException {
        if (s == null) {
            return null;
        }
        Class type = s.getClass();
        if (type.isArray()) {
            Object o = cache.get(s);
            return o != null ? (T) o : deepCopyArray(cache, s);
        }
        if (isImmutableForDeepCopy(s)) {
            // 不可变的类型直接返回
            return s;
        }
        // 源对象地址
        Object o = cache.get(s);
        if (o != null) {
            // 如果已经拷贝过了,直接返回,避免循环
            return (T) o;
        }
        ClassCopyDesc copyer = getOrParseUnsafeField(type);
        T t = (T) UnsafeUtils.allocateInstance(type);
        // 把拷贝出来的对象缓存起来
        cache.put(s, t);
        for (UnsafeField unsafeField : copyer.getFields()) {
            Class fType = unsafeField.getType();
            long offset = unsafeField.getOffset();
            // 基础类型直接赋值就行了
            if (fType == boolean.class) {
                UnsafeUtils.putBoolean(t, offset, UnsafeUtils.getBoolean(s, offset));
            } else if (fType == char.class) {
                UnsafeUtils.putChar(t, offset, UnsafeUtils.getChar(s, offset));
            } else if (fType == byte.class) {
                UnsafeUtils.putByte(t, offset, UnsafeUtils.getByte(s, offset));
            } else if (fType == short.class) {
                UnsafeUtils.putShort(t, offset, UnsafeUtils.getShort(s, offset));
            } else if (fType == int.class) {
                UnsafeUtils.putInt(t, offset, UnsafeUtils.getInt(s, offset));
            } else if (fType == long.class) {
                UnsafeUtils.putLong(t, offset, UnsafeUtils.getLong(s, offset));
            } else if (fType == float.class) {
                UnsafeUtils.putFloat(t, offset, UnsafeUtils.getFloat(s, offset));
            } else if (fType == double.class) {
                UnsafeUtils.putDouble(t, offset, UnsafeUtils.getDouble(s, offset));
            } else {
                UnsafeUtils.putObject(t, offset, deepCopy(cache, UnsafeUtils.getObject(s, offset)));
            }
        }
        return t;
    }

    private static boolean isImmutableForDeepCopy(Object o) {
        return o instanceof Class || isEnum(o) || isAnnotation(o) || unmodifiedClass.contains(o.getClass());
    }

    private static  T deepCopyArray(Map cache, T srcArr) throws InstantiationException {
        Class component = srcArr.getClass().getComponentType();
        int length = Array.getLength(srcArr);
        Object targetArr = Array.newInstance(component, length);
        if (component.isPrimitive() || component.isEnum() || unmodifiedClass.contains(component)) {
            // 基本类型/枚举/不可变类的对象 直接拷贝
            System.arraycopy(srcArr, 0, targetArr, 0, length);
        } else {
            Object o = cache.get(srcArr);
            if (o != null) {
                return (T) o;
            }
            // 对象拷贝
            for (int i = 0; i < length; i++) {
                Array.set(targetArr, i, deepCopy(cache, Array.get(srcArr, i)));
            }
        }
        return (T) targetArr;
    }

    private static  ClassCopyDesc getOrParseUnsafeField(Class clazz) {
        ClassCopyDesc copyer = (ClassCopyDesc) unsafeFieldMap.get(clazz);
        if (copyer == null) {
            copyer = ClassCopyDesc.of(clazz);
            unsafeFieldMap.put(clazz, copyer);
        }
        return copyer;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy