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

com.alipay.sofa.common.utils.ClassUtil Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alipay.sofa.common.utils;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

/**
 *
 * @author luoguimu123
 * @version $Id: ClassUtil.java, v 0.1 2017年08月01日 下午12:01 luoguimu123 Exp $
 */
public class ClassUtil {
    private static final Map TYPE_MAP = Collections.synchronizedMap(new WeakHashMap());

    public ClassUtil() {
    }

    public static boolean isPresent(String className) {
        try {
            Class.forName(className);
            return true;
        } catch (Throwable throwable) {
            return false;
        }
    }

    public static boolean isPresent(String className, ClassLoader classLoader) {
        try {
            classLoader.loadClass(className);
            return true;
        } catch (Throwable throwable) {
            return false;
        }
    }

    public static String getClassNameForObject(Object object) {
        return object == null ? null : getClassName(object.getClass().getName(), true);
    }

    public static String getClassName(Class clazz) {
        return clazz == null ? null : getClassName(clazz.getName(), true);
    }

    public static String getClassName(String className) {
        return getClassName(className, true);
    }

    private static String getClassName(String className, boolean processInnerClass) {
        if (StringUtil.isEmpty(className)) {
            return className;
        } else {
            if (processInnerClass) {
                className = className.replace('$', '.');
            }

            int length = className.length();
            int dimension = 0;

            for (int i = 0; i < length && className.charAt(i) == 91; ++dimension) {
                ++i;
            }

            if (dimension == 0) {
                return className;
            } else if (length <= dimension) {
                return className;
            } else {
                StringBuffer componentTypeName = new StringBuffer();
                switch (className.charAt(dimension)) {
                    case 'B':
                        componentTypeName.append("byte");
                        break;
                    case 'C':
                        componentTypeName.append("char");
                        break;
                    case 'D':
                        componentTypeName.append("double");
                        break;
                    case 'E':
                    case 'G':
                    case 'H':
                    case 'K':
                    case 'M':
                    case 'N':
                    case 'O':
                    case 'P':
                    case 'Q':
                    case 'R':
                    case 'T':
                    case 'U':
                    case 'V':
                    case 'W':
                    case 'X':
                    case 'Y':
                    case 'F':
                        componentTypeName.append("float");
                        break;
                    case 'I':
                        componentTypeName.append("int");
                        break;
                    case 'J':
                        componentTypeName.append("long");
                        break;
                    case 'L':
                        if (className.charAt(length - 1) != 59 || length <= dimension + 2) {
                            return className;
                        }

                        componentTypeName.append(className.substring(dimension + 1, length - 1));
                        break;
                    case 'S':
                        componentTypeName.append("short");
                        break;
                    case 'Z':
                        componentTypeName.append("boolean");
                    default:
                        return className;
                }

                for (int i = 0; i < dimension; ++i) {
                    componentTypeName.append("[]");
                }

                return componentTypeName.toString();
            }
        }
    }

    public static String getShortClassNameForObject(Object object) {
        return object == null ? null : getShortClassName(object.getClass().getName());
    }

    public static String getShortClassName(Class clazz) {
        return clazz == null ? null : getShortClassName(clazz.getName());
    }

    public static String getShortClassName(String className) {
        if (StringUtil.isEmpty(className)) {
            return className;
        } else {
            className = getClassName(className, false);
            char[] chars = className.toCharArray();
            int lastDot = 0;

            for (int i = 0; i < chars.length; ++i) {
                if (chars[i] == 46) {
                    lastDot = i + 1;
                } else if (chars[i] == 36) {
                    chars[i] = 46;
                }
            }

            return new String(chars, lastDot, chars.length - lastDot);
        }
    }

    public static String getPackageNameForObject(Object object) {
        return object == null ? null : getPackageName(object.getClass().getName());
    }

    public static String getPackageName(Class clazz) {
        return clazz == null ? null : getPackageName(clazz.getName());
    }

    public static String getPackageName(String className) {
        if (StringUtil.isEmpty(className)) {
            return null;
        } else {
            className = getClassName(className, false);
            int i = className.lastIndexOf(46);
            return i == -1 ? "" : className.substring(0, i);
        }
    }

    public static String getClassNameForObjectAsResource(Object object) {
        return object == null ? null : object.getClass().getName().replace('.', '/') + ".class";
    }

    public static String getClassNameAsResource(Class clazz) {
        return clazz == null ? null : clazz.getName().replace('.', '/') + ".class";
    }

    public static String getClassNameAsResource(String className) {
        return className == null ? null : className.replace('.', '/') + ".class";
    }

    public static String getPackageNameForObjectAsResource(Object object) {
        return object == null ? null : getPackageNameForObject(object).replace('.', '/');
    }

    public static String getPackageNameAsResource(Class clazz) {
        return clazz == null ? null : getPackageName(clazz).replace('.', '/');
    }

    public static String getPackageNameAsResource(String className) {
        return className == null ? null : getPackageName(className).replace('.', '/');
    }

    public static Class getArrayClass(Class componentType, int dimension) {
        return dimension <= 0 ? componentType : (componentType == null ? null : Array.newInstance(
            componentType, new int[dimension]).getClass());
    }

    public static Class getArrayComponentType(Class type) {
        return type == null ? null : getTypeInfo(type).getArrayComponentType();
    }

    public static int getArrayDimension(Class clazz) {
        return clazz == null ? -1 : getTypeInfo(clazz).getArrayDimension();
    }

    public static List getSuperclasses(Class clazz) {
        return clazz == null ? null : getTypeInfo(clazz).getSuperclasses();
    }

    public static List getInterfaces(Class clazz) {
        return clazz == null ? null : getTypeInfo(clazz).getInterfaces();
    }

    public static boolean isInnerClass(Class clazz) {
        return clazz == null ? false : StringUtil.contains(clazz.getName(), '$');
    }

    public static boolean isAssignable(Class[] classes, Class[] fromClasses) {
        if (!ArrayUtil.isSameLength(fromClasses, classes)) {
            return false;
        } else {
            if (fromClasses == null) {
                fromClasses = ArrayUtil.EMPTY_CLASS_ARRAY;
            }

            if (classes == null) {
                classes = ArrayUtil.EMPTY_CLASS_ARRAY;
            }

            for (int i = 0; i < fromClasses.length; ++i) {
                if (!isAssignable(classes[i], fromClasses[i])) {
                    return false;
                }
            }

            return true;
        }
    }

    public static boolean isAssignable(Class clazz, Class fromClass) {
        if (clazz == null) {
            return false;
        } else if (fromClass == null) {
            return !clazz.isPrimitive();
        } else if (clazz.isAssignableFrom(fromClass)) {
            return true;
        } else {
            if (clazz.isPrimitive()) {
                if (Boolean.TYPE.equals(clazz)) {
                    return Boolean.class.equals(fromClass);
                }

                if (Byte.TYPE.equals(clazz)) {
                    return Byte.class.equals(fromClass);
                }

                if (Character.TYPE.equals(clazz)) {
                    return Character.class.equals(fromClass);
                }

                if (Short.TYPE.equals(clazz)) {
                    return Short.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
                           || Byte.class.equals(fromClass);
                }

                if (Integer.TYPE.equals(clazz)) {
                    return Integer.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
                           || Byte.class.equals(fromClass) || Short.TYPE.equals(fromClass)
                           || Short.class.equals(fromClass) || Character.TYPE.equals(fromClass)
                           || Character.class.equals(fromClass);
                }

                if (Long.TYPE.equals(clazz)) {
                    return Long.class.equals(fromClass) || Integer.TYPE.equals(fromClass)
                           || Integer.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
                           || Byte.class.equals(fromClass) || Short.TYPE.equals(fromClass)
                           || Short.class.equals(fromClass) || Character.TYPE.equals(fromClass)
                           || Character.class.equals(fromClass);
                }

                if (Float.TYPE.equals(clazz)) {
                    return Float.class.equals(fromClass) || Long.TYPE.equals(fromClass)
                           || Long.class.equals(fromClass) || Integer.TYPE.equals(fromClass)
                           || Integer.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
                           || Byte.class.equals(fromClass) || Short.TYPE.equals(fromClass)
                           || Short.class.equals(fromClass) || Character.TYPE.equals(fromClass)
                           || Character.class.equals(fromClass);
                }

                if (Double.TYPE.equals(clazz)) {
                    return Double.class.equals(fromClass) || Float.TYPE.equals(fromClass)
                           || Float.class.equals(fromClass) || Long.TYPE.equals(fromClass)
                           || Long.class.equals(fromClass) || Integer.TYPE.equals(fromClass)
                           || Integer.class.equals(fromClass) || Byte.TYPE.equals(fromClass)
                           || Byte.class.equals(fromClass) || Short.TYPE.equals(fromClass)
                           || Short.class.equals(fromClass) || Character.TYPE.equals(fromClass)
                           || Character.class.equals(fromClass);
                }
            }

            return false;
        }
    }

    protected static ClassUtil.TypeInfo getTypeInfo(Class type) {
        if (type == null) {
            throw new IllegalArgumentException("Parameter clazz should not be null");
        } else {
            synchronized (TYPE_MAP) {
                ClassUtil.TypeInfo classInfo = (ClassUtil.TypeInfo) TYPE_MAP.get(type);
                if (classInfo == null) {
                    classInfo = new ClassUtil.TypeInfo(type);
                    TYPE_MAP.put(type, classInfo);
                }

                return classInfo;
            }
        }
    }

    public static Class getPrimitiveType(Class clazz) {
        return clazz == null ? null : (clazz.isPrimitive() ? clazz
            : (clazz.equals(Long.class) ? Long.TYPE : (clazz.equals(Integer.class) ? Integer.TYPE
                : (clazz.equals(Short.class) ? Short.TYPE : (clazz.equals(Byte.class) ? Byte.TYPE
                    : (clazz.equals(Double.class) ? Double.TYPE
                        : (clazz.equals(Float.class) ? Float.TYPE
                            : (clazz.equals(Boolean.class) ? Boolean.TYPE : (clazz
                                .equals(Character.class) ? Character.TYPE : null)))))))));
    }

    public static Class getNonPrimitiveType(Class clazz) {
        return clazz == null ? null : (!clazz.isPrimitive() ? clazz
            : (clazz.equals(Long.TYPE) ? Long.class : (clazz.equals(Integer.TYPE) ? Integer.class
                : (clazz.equals(Short.TYPE) ? Short.class : (clazz.equals(Byte.TYPE) ? Byte.class
                    : (clazz.equals(Double.TYPE) ? Double.class
                        : (clazz.equals(Float.TYPE) ? Float.class
                            : (clazz.equals(Boolean.TYPE) ? Boolean.class : (clazz
                                .equals(Character.TYPE) ? Character.class : null)))))))));
    }

    protected static class TypeInfo {
        private Class type;
        private Class componentType;
        private int   dimension;
        private List  superclasses;
        private List  interfaces;

        private TypeInfo(Class type) {
            this.superclasses = new ArrayList(2);
            this.interfaces = new ArrayList(2);
            this.type = type;
            Class componentType = null;
            if (type.isArray()) {
                componentType = type;

                do {
                    componentType = componentType.getComponentType();
                    ++this.dimension;
                } while (componentType.isArray());
            }

            this.componentType = componentType;
            Class superComponentType;
            Class componentInterface;
            if (this.dimension > 0) {
                componentType = this.getNonPrimitiveType(componentType);
                superComponentType = componentType.getSuperclass();
                if (superComponentType == null && !Object.class.equals(componentType)) {
                    superComponentType = Object.class;
                }

                if (superComponentType != null) {
                    componentInterface = ClassUtil
                        .getArrayClass(superComponentType, this.dimension);
                    this.superclasses.add(componentInterface);
                    this.superclasses
                        .addAll(ClassUtil.getTypeInfo(componentInterface).superclasses);
                } else {
                    for (int i = this.dimension - 1; i >= 0; --i) {
                        this.superclasses.add(ClassUtil.getArrayClass(Object.class, i));
                    }
                }
            } else {
                type = this.getNonPrimitiveType(type);
                superComponentType = type.getSuperclass();
                if (superComponentType != null) {
                    this.superclasses.add(superComponentType);
                    this.superclasses
                        .addAll(ClassUtil.getTypeInfo(superComponentType).superclasses);
                }
            }

            if (this.dimension == 0) {
                Class[] typeInterfaces = type.getInterfaces();
                List set = new ArrayList();

                Class interfaceClass;
                for (int i = 0; i < typeInterfaces.length; ++i) {
                    interfaceClass = typeInterfaces[i];
                    set.add(interfaceClass);
                    set.addAll(ClassUtil.getTypeInfo(interfaceClass).interfaces);
                }

                Iterator i = this.superclasses.iterator();

                while (i.hasNext()) {
                    interfaceClass = (Class) i.next();
                    set.addAll(ClassUtil.getTypeInfo(interfaceClass).interfaces);
                }

                i = set.iterator();

                while (i.hasNext()) {
                    interfaceClass = (Class) i.next();
                    if (!this.interfaces.contains(interfaceClass)) {
                        this.interfaces.add(interfaceClass);
                    }
                }
            } else {
                Iterator i = ClassUtil.getTypeInfo(componentType).interfaces.iterator();

                while (i.hasNext()) {
                    componentInterface = (Class) i.next();
                    this.interfaces
                        .add(ClassUtil.getArrayClass(componentInterface, this.dimension));
                }
            }

        }

        private Class getNonPrimitiveType(Class type) {
            if (type.isPrimitive()) {
                if (Integer.TYPE.equals(type)) {
                    type = Integer.class;
                } else if (Long.TYPE.equals(type)) {
                    type = Long.class;
                } else if (Short.TYPE.equals(type)) {
                    type = Short.class;
                } else if (Byte.TYPE.equals(type)) {
                    type = Byte.class;
                } else if (Float.TYPE.equals(type)) {
                    type = Float.class;
                } else if (Double.TYPE.equals(type)) {
                    type = Double.class;
                } else if (Boolean.TYPE.equals(type)) {
                    type = Boolean.class;
                } else if (Character.TYPE.equals(type)) {
                    type = Character.class;
                }
            }

            return type;
        }

        public Class getType() {
            return this.type;
        }

        public Class getArrayComponentType() {
            return this.componentType;
        }

        public int getArrayDimension() {
            return this.dimension;
        }

        public List getSuperclasses() {
            return Collections.unmodifiableList(this.superclasses);
        }

        public List getInterfaces() {
            return Collections.unmodifiableList(this.interfaces);
        }
    }

    /**
     * Get field from specified object, will lookup in super class until found
     */
    @SuppressWarnings("unchecked")
    public static  T getField(String fieldName, Object o) {
        Class klass = o.getClass();
        while (klass != null) {
            try {
                Field f = klass.getDeclaredField(fieldName);
                f.setAccessible(true);
                return (T) f.get(o);
            } catch (Exception e) {
                klass = klass.getSuperclass();
            }
        }
        return null;
    }

    /**
     * Set field of specified object to value, will try to operate on super class until success
     */
    public static  void setField(String fieldName, Object o, T value) {
        Class klass = o.getClass();
        while (klass != null) {
            try {
                Field f = klass.getDeclaredField(fieldName);
                f.setAccessible(true);
                f.set(o, value);
                return;
            } catch (Exception e) {
                klass = klass.getSuperclass();
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy