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

com.truthbean.common.mini.util.ClassHelper Maven / Gradle / Ivy

There is a newer version: 0.5.4-RELEASE
Show newest version
/**
 * Copyright (c) 2021 TruthBean(Rogar·Q)
 * Debbie is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 * http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package com.truthbean.common.mini.util;

import com.truthbean.common.mini.CommonConstants;

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

/**
 * 

类相关的工具类

* * @author TruthBean/Rogar·Q * @since 0.0.1 * Created on 2018-01-08 22:07 * @version 0.0.1 */ public class ClassHelper { /** *

Constructor for ClassHelper.

*/ protected ClassHelper() { } /** * Suffix for array class names: "[]" */ private static final String ARRAY_SUFFIX = "[]"; /** * Prefix for internal array class names: "[L" */ private static final String INTERNAL_ARRAY_PREFIX = "[L"; /** * Map with primitive type name as key and corresponding primitive type as * value, for example: "int" -> "int.class". */ private static final Map> PRIMITIVE_TYPE_NAME_MAP = new HashMap<>(16); /** * Map with primitive wrapper type as key and corresponding primitive type * as value, for example: Integer.class -> int.class. */ private static final Map, Class> PRIMITIVE_WRAPPER_TYPE_MAP = new HashMap<>(8); private static final Map> CLASS_MAP = new HashMap<>(17); private static final Map, Class> BASE_TYPE_MAP = new HashMap<>(8); static { PRIMITIVE_WRAPPER_TYPE_MAP.put(Boolean.class, boolean.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Byte.class, byte.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Character.class, char.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Double.class, double.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Float.class, float.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Integer.class, int.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Long.class, long.class); PRIMITIVE_WRAPPER_TYPE_MAP.put(Short.class, short.class); Set> primitiveTypeNames = new HashSet<>(16); primitiveTypeNames.addAll(PRIMITIVE_WRAPPER_TYPE_MAP.values()); primitiveTypeNames.addAll(Arrays .asList(boolean[].class, byte[].class, char[].class, double[].class, float[].class, int[].class, long[].class, short[].class)); for (Class primitiveClass : primitiveTypeNames) { PRIMITIVE_TYPE_NAME_MAP.put(primitiveClass.getName(), primitiveClass); } CLASS_MAP.put(Integer.class.getName(), Integer.class); CLASS_MAP.put(int.class.getName(), int.class); CLASS_MAP.put(Short.class.getName(), Short.class); CLASS_MAP.put(short.class.getName(), short.class); CLASS_MAP.put(long.class.getName(), long.class); CLASS_MAP.put(Long.class.getName(), Long.class); CLASS_MAP.put(float.class.getName(), Float.class); CLASS_MAP.put(Float.class.getName(), float.class); CLASS_MAP.put(Double.class.getName(), Double.class); CLASS_MAP.put(double.class.getName(), double.class); CLASS_MAP.put(Boolean.class.getName(), Boolean.class); CLASS_MAP.put(boolean.class.getName(), boolean.class); CLASS_MAP.put(Character.class.getName(), Character.class); CLASS_MAP.put(char.class.getName(), char.class); CLASS_MAP.put(Byte.class.getName(), Byte.class); CLASS_MAP.put(byte.class.getName(), byte.class); CLASS_MAP.put(Object.class.getName(), Object.class); BASE_TYPE_MAP.put(int.class, Integer.class); BASE_TYPE_MAP.put(short.class, Short.class); BASE_TYPE_MAP.put(long.class, Long.class); BASE_TYPE_MAP.put(float.class, Float.class); BASE_TYPE_MAP.put(double.class, Double.class); BASE_TYPE_MAP.put(boolean.class, Boolean.class); BASE_TYPE_MAP.put(char.class, Character.class); BASE_TYPE_MAP.put(byte.class, Byte.class); } /** * forName by current thread class loader * * @param name class name * @return class * @throws java.lang.ClassNotFoundException if the class not found */ public static Class forNameWithThreadContextClassLoader(String name) throws ClassNotFoundException { return forName(name, Thread.currentThread().getContextClassLoader()); } /** *

forNameWithCallerClassLoader.

* * @param name a {@link java.lang.String} object. * @param caller a {@link java.lang.Class} object. * @return a {@link java.lang.Class} object. * @throws java.lang.ClassNotFoundException if any. */ public static Class forNameWithCallerClassLoader(String name, Class caller) throws ClassNotFoundException { return forName(name, caller.getClassLoader()); } /** *

getCallerClassLoader.

* * @param caller a {@link java.lang.Class} object. * @return a {@link java.lang.ClassLoader} object. */ public static ClassLoader getCallerClassLoader(Class caller) { return caller.getClassLoader(); } /** *

getClassLoader.

* * @param clazz a {@link java.lang.Class} object. * @return a {@link java.lang.ClassLoader} object. */ public static ClassLoader getClassLoader(Class clazz) { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { // Cannot access thread context ClassLoader - falling back... } if (cl == null) { // No thread context class loader -> use class loader of this class. cl = clazz.getClassLoader(); if (cl == null) { try { cl = ClassLoader.getPlatformClassLoader(); } catch (Throwable ignored1) { // getClassLoader() returning null indicates the bootstrap ClassLoader try { cl = ClassLoader.getSystemClassLoader(); } catch (Throwable ignored2) { // Cannot access system ClassLoader - oh well, maybe the caller can live with null... } } } } return cl; } /** *

getDefaultClassLoader.

* * @return a {@link java.lang.ClassLoader} object. */ public static ClassLoader getDefaultClassLoader() { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { // Cannot access thread context ClassLoader - falling back... } if (cl == null) { // No thread context class loader -> use class loader of this class. cl = ClassHelper.class.getClassLoader(); if (cl == null) { try { cl = ClassLoader.getPlatformClassLoader(); } catch (Throwable ignored1) { // getClassLoader() returning null indicates the bootstrap ClassLoader try { cl = ClassLoader.getSystemClassLoader(); } catch (Throwable ignored2) { // Cannot access system ClassLoader - oh well, maybe the caller can live with null... } } } } return cl; } /** *

classForName.

* * @param className a {@link java.lang.String} object. * @return a {@link java.lang.Class} object. * @throws java.lang.ClassNotFoundException if any. */ public static Class classForName(String className) throws ClassNotFoundException { ClassLoader classLoader = getDefaultClassLoader(); return classLoader.loadClass(className); } /** * Replacement for Class.forName() that also returns Class * instances for primitives (like "int") and array class names (like * "String[]"). * * @param name the name of the Class * @param classLoader the class loader to use (may be null, * which indicates the default class loader) * @return Class instance for the supplied name * @throws java.lang.ClassNotFoundException if the class was not found * @throws java.lang.LinkageError if the class file could not be loaded * @see Class#forName(String, boolean, ClassLoader) */ public static Class forName(String name, ClassLoader classLoader) throws ClassNotFoundException, LinkageError { Class clazz = resolvePrimitiveClassName(name); if (clazz != null) { return clazz; } // "java.lang.String[]" style arrays if (name.endsWith(ARRAY_SUFFIX)) { String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length()); Class elementClass = forName(elementClassName, classLoader); return Array.newInstance(elementClass, 0).getClass(); } // "[Ljava.lang.String;" style arrays int internalArrayMarker = name.indexOf(INTERNAL_ARRAY_PREFIX); if (internalArrayMarker != -1 && name.endsWith(CommonConstants.COLON)) { String elementClassName = null; if (internalArrayMarker == 0) { elementClassName = name .substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1); } else if (name.startsWith(CommonConstants.LEFT_CURLY_BRACKET)) { elementClassName = name.substring(1); } Class elementClass = forName(elementClassName, classLoader); return Array.newInstance(elementClass, 0).getClass(); } ClassLoader classLoaderToUse = classLoader; if (classLoaderToUse == null) { classLoaderToUse = getClassLoader(ClassHelper.class); } return classLoaderToUse.loadClass(name); } /** * Resolve the given class name as primitive class, if appropriate, * according to the JVM's naming rules for primitive classes. *

* Also supports the JVM's internal class names for primitive arrays. Does * not support the "[]" suffix notation for primitive arrays; this is * only supported by {@link #forName}. * * @param name the name of the potentially primitive class * @return the primitive class, or null if the name does not * denote a primitive class or primitive array class */ public static Class resolvePrimitiveClassName(String name) { Class result = null; // Most class names will be quite long, considering that they // SHOULD sit in a package, so a length check is worthwhile. if (name != null && name.length() <= CommonConstants.PRIMITIVE_CLASS_NUMBER) { // Could be a primitive - likely. result = PRIMITIVE_TYPE_NAME_MAP.get(name); } return result; } /** *

toShortString.

* * @param obj a {@link java.lang.Object} object. * @return a {@link java.lang.String} object. */ public static String toShortString(Object obj) { if (obj == null) { return "null"; } return obj.getClass().getSimpleName() + "@" + System.identityHashCode(obj); } /** *

getWrapperClass.

* * @param baseType a {@link java.lang.Class} object. * @return a {@link java.lang.Class} object. */ public static Class getWrapperClass(Class baseType) { for (Map.Entry, Class> classClassEntry : BASE_TYPE_MAP.entrySet()) { if (classClassEntry.getKey() == baseType) { return classClassEntry.getValue(); } } return baseType; } /** *

getClass.

* * @param className a {@link java.lang.String} object. * @return a {@link java.lang.Class} object. */ public static Class getClass(String className) { return CLASS_MAP.get(className); } /** *

isInt.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isInt(Class clazz) { return clazz == Integer.class || clazz == int.class; } /** *

isShort.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isShort(Class clazz) { return clazz == Short.class || clazz == short.class; } /** *

isLong.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isLong(Class clazz) { return clazz == Long.class || clazz == long.class; } /** *

isFloat.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isFloat(Class clazz) { return clazz == float.class || clazz == Float.class; } /** *

isDouble.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isDouble(Class clazz) { return clazz == Double.class || clazz == double.class; } /** *

isBoolean.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isBoolean(Class clazz) { return clazz == Boolean.class || clazz == boolean.class; } /** *

isChar.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isChar(Class clazz) { return clazz == Character.class || clazz == char.class; } /** *

isByte.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isByte(Class clazz) { return clazz == Byte.class || clazz == byte.class; } /** *

isObject.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isObject(Class clazz) { return clazz == Object.class; } /** *

isBaseType.

* * @param type a {@link java.lang.reflect.Type} object. * @return a boolean. */ public static boolean isBaseType(java.lang.reflect.Type type) { if (type instanceof Class) { Class clazz = (Class) type; return isBoolean(clazz) || isDouble(clazz) || isFloat(clazz) || isInt(clazz) || isLong(clazz) || isShort(clazz) || isChar(clazz) || isByte(clazz) || clazz == String.class || isObject(clazz); } return false; } /** *

isRawBaseType.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isRawBaseType(Class clazz) { return boolean.class == clazz || double.class == clazz || float.class == clazz || int.class == clazz || long.class == clazz || short.class == clazz || char.class == clazz || byte.class == clazz; } /** *

unwarp.

* * @param value a {@link java.lang.Object} object. * @return a {@link java.lang.Object} object. */ public static Object unwarp(Object value) { if (value instanceof Integer) { try { return ((Integer) value).intValue(); } catch (NumberFormatException e) { logger.log(System.Logger.Level.ERROR, "", e); return null; } } if (value instanceof Short) { try { return ((Short) value).shortValue(); } catch (NumberFormatException e) { logger.log(System.Logger.Level.ERROR, "", e); return null; } } if (value instanceof Long) { try { return ((Long) value).longValue(); } catch (NumberFormatException e) { logger.log(System.Logger.Level.ERROR, "", e); return null; } } if (value instanceof Float) { try { return ((Float) value).floatValue(); } catch (NumberFormatException e) { logger.log(System.Logger.Level.ERROR, "", e); return null; } } if (value instanceof Double) { try { return ((Double) value).doubleValue(); } catch (NumberFormatException e) { logger.log(System.Logger.Level.ERROR, "", e); return null; } } if (value instanceof Boolean) { try { return ((Boolean) value).booleanValue(); } catch (Exception e) { logger.log(System.Logger.Level.ERROR, "", e); return null; } } if (value instanceof Byte) { try { return ((Byte) value).byteValue(); } catch (NumberFormatException e) { logger.log(System.Logger.Level.ERROR, "", e); return null; } } if (value instanceof Character) { try { return ((Character) value).charValue(); } catch (Exception e) { logger.log(System.Logger.Level.ERROR, "", e); return null; } } return null; } /** *

isSameType.

* * @param aType a {@link java.lang.Class} object. * @param bType a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isSameType(Class aType, Class bType) { return (isInt(aType) && isInt(bType) || (isShort(aType) && isShort(bType)) || (isLong(aType) && isLong(bType)) || (isFloat(aType)) && isFloat(bType) || (isDouble(aType) && isDouble(bType)) || (isBoolean(aType) && isBoolean(bType)) || (isChar(aType) && isChar(bType)) || (isByte(aType)) && isByte(bType) || (aType == bType)); } /** *

isArrayType.

* * @param clazz a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isArrayType(Class clazz) { return clazz == Set.class || clazz == Map.class || clazz == List.class; } /** *

isArrayType.

* * @param type a {@link java.lang.reflect.Type} object. * @return a boolean. */ public static boolean isArrayType(java.lang.reflect.Type type) { if (type instanceof Class) { Class clazz = (Class) type; return clazz == Set.class || clazz == Map.class || clazz == List.class; } else if (type instanceof ParameterizedType) { java.lang.reflect.Type rawType = ((ParameterizedType) type).getRawType(); return rawType == Set.class || rawType == Map.class || rawType == List.class; } return false; } /** *

isTimeType.

* * @param type a {@link java.lang.reflect.Type} object. * @return a boolean. */ public static boolean isTimeType(java.lang.reflect.Type type) { if (type instanceof Class) { Class clazz = (Class) type; return clazz == Date.class || clazz == Calendar.class || Date.class.isAssignableFrom(clazz) || (clazz.getPackageName().startsWith("java.time")); } return false; } /** *

isAbstractOrInterface.

* * @param type a {@link java.lang.Class} object. * @return a boolean. */ public static boolean isAbstractOrInterface(Class type) { return Modifier.isAbstract(type.getModifiers()) || type.isInterface(); } /** *

hasDefaultConstructor.

* * @param type a {@link java.lang.Class} object. * @return a boolean. */ public static boolean hasDefaultConstructor(Class type) { Constructor[] constructors = type.getConstructors(); for (Constructor constructor : constructors) { if (constructor.getParameterCount() == 0) { return true; } } return false; } /** *

getExceptions.

* * @param exceptionTypes an array of {@link java.lang.Class} objects. * @return an array of {@link java.lang.String} objects. */ public static String[] getExceptions(Class[] exceptionTypes) { if (exceptionTypes != null && exceptionTypes.length > 0) { String[] exceptions = new String[exceptionTypes.length]; for (int i = 0; i < exceptionTypes.length; i++) { Class exceptionType = exceptionTypes[i]; exceptions[i] = exceptionType.getName().replace(".", "/"); } return exceptions; } return null; } /** *

isOrValueOf.

* * @param clazz a {@link java.lang.Class} object. * @param target a {@link java.lang.String} object. * @return a boolean. */ public static boolean isOrValueOf(Class clazz, String target) { if (target.getClass().equals(clazz)) { return true; } else { if (NumericUtils.isInteger(target)) { return clazz == Integer.class || clazz == int.class || clazz == Short.class || clazz == short.class || clazz == Long.class || clazz == long.class || clazz == BigInteger.class; } if (NumericUtils.isDecimal(target)) { return clazz == Float.class || clazz == float.class || clazz == Double.class || clazz == double.class || clazz == BigDecimal.class; } return (CommonConstants.TRUE.equalsIgnoreCase(target.strip()) || CommonConstants.FALSE.equalsIgnoreCase(target.trim())) && (clazz == Boolean.class || clazz == boolean.class); } } /** *

filterAnnotation.

* * @param annotationType a {@link java.lang.Class} object. * @return a boolean. */ public static boolean filterAnnotation(Class annotationType) { return !Target.class.equals(annotationType) && !Retention.class.equals(annotationType) && !Repeatable.class.equals(annotationType) && !Inherited.class.equals(annotationType) && !Documented.class.equals(annotationType) && !Deprecated.class.equals(annotationType) && !Native.class.equals(annotationType) && !SafeVarargs.class.equals(annotationType) && !FunctionalInterface.class.equals(annotationType) && !SuppressWarnings.class.equals(annotationType) && !Override.class.equals(annotationType); } /** *

getSuperGenericType.

* * @param clazz a {@link java.lang.Class} object. * @param a T object. * @return a {@link java.lang.Class} object. */ @SuppressWarnings("unchecked") public static Class getSuperGenericType(Class clazz) { return (Class) getSuperClassGenricType(clazz, 0); } /** * 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型 * 如:public EmployeeDao extends BaseDao<Employee, String> * * @param clazz class * @param index index * @return class */ public static Class getSuperClassGenricType(Class clazz, int index) { Type genType = clazz.getGenericSuperclass(); if (!(genType instanceof ParameterizedType)) { return Object.class; } Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); if (index >= params.length || index < 0) { return Object.class; } if (!(params[index] instanceof Class)) { return Object.class; } return (Class) params[index]; } private static final System.Logger logger = System.getLogger(ClassHelper.class.getName()); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy