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

com.virjar.sekiro.utils.ReflectUtil Maven / Gradle / Ivy

Go to download

ratel api,used for developer on ratel system,an extension for xposed framewrok,ratel api compatable with original xposed framework

There is a newer version: 1.0.5
Show newest version
package com.virjar.sekiro.utils;


import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;


/**
 * Created by virjar on 2018/8/28.
* 反射工具,可以在没有xposed的环境下,安全运行 */ public class ReflectUtil { private static final HashMap fieldCache = new HashMap<>(); private static final HashMap methodCache = new HashMap<>(); private static final HashMap> constructorCache = new HashMap<>(); private static void makeAccessible(Field field) { if (!Modifier.isPublic(field.getModifiers())) { field.setAccessible(true); } } private static Field getDeclaredField(Object object, String filedName) { return findField(object.getClass(), filedName); } public static void setFieldValue(Object object, String fieldName, Object value) { try { findField(object.getClass(), fieldName).set(object, value); } catch (IllegalAccessException e) { throw new IllegalStateException(e); } } @SuppressWarnings("unchecked") public static T getFieldValue(Object object, String fieldName) { try { return (T) findField(object.getClass(), fieldName).get(object); } catch (IllegalAccessException e) { throw new IllegalStateException(e); } } @SuppressWarnings("unchecked") public static T getStaticFiled(Class clazz, String filedName) { try { return (T) findField(clazz, filedName).get(null); } catch (IllegalAccessException e) { throw new IllegalStateException(e); } } //################################################################################################# /** * Calls an instance or static method of the given object. * The method is resolved using {@link #findMethodBestMatch(Class, String, Object...)}. * * @param obj The object instance. A class reference is not sufficient! * @param methodName The method name. * @param args The arguments for the method call. * @throws NoSuchMethodError In case no suitable method was found. */ public static Object callMethod(Object obj, String methodName, Object... args) { try { return findMethodBestMatch(obj.getClass(), methodName, args).invoke(obj, args); } catch (IllegalAccessException e) { // should not happen e.printStackTrace(); throw new IllegalAccessError(e.getMessage()); } catch (IllegalArgumentException e) { throw e; } catch (InvocationTargetException e) { throw new IllegalStateException(e.getCause()); } } /** * Calls an instance or static method of the given object. * See {@link #callMethod(Object, String, Object...)}. *

*

This variant allows you to specify parameter types, which can help in case there are multiple * methods with the same name, especially if you call it with {@code null} parameters. */ public static Object callMethod(Object obj, String methodName, Class[] parameterTypes, Object... args) { try { return findMethodBestMatch(obj.getClass(), methodName, parameterTypes, args).invoke(obj, args); } catch (IllegalAccessException e) { // should not happen e.printStackTrace(); throw new IllegalAccessError(e.getMessage()); } catch (IllegalArgumentException e) { throw e; } catch (InvocationTargetException e) { throw new IllegalStateException(e.getCause()); } } /** * Calls a static method of the given class. * The method is resolved using {@link #findMethodBestMatch(Class, String, Object...)}. * * @param clazz The class reference. * @param methodName The method name. * @param args The arguments for the method call. * @throws NoSuchMethodError In case no suitable method was found. */ public static Object callStaticMethod(Class clazz, String methodName, Object... args) { try { return findMethodBestMatch(clazz, methodName, args).invoke(null, args); } catch (IllegalAccessException e) { // should not happen e.printStackTrace(); throw new IllegalAccessError(e.getMessage()); } catch (IllegalArgumentException e) { throw e; } catch (InvocationTargetException e) { throw new IllegalStateException(e.getCause()); } } /** * Calls a static method of the given class. * See {@link #callStaticMethod(Class, String, Object...)}. *

*

This variant allows you to specify parameter types, which can help in case there are multiple * methods with the same name, especially if you call it with {@code null} parameters. */ public static Object callStaticMethod(Class clazz, String methodName, Class[] parameterTypes, Object... args) { try { return findMethodBestMatch(clazz, methodName, parameterTypes, args).invoke(null, args); } catch (IllegalAccessException e) { // should not happen e.printStackTrace(); throw new IllegalAccessError(e.getMessage()); } catch (IllegalArgumentException e) { throw e; } catch (InvocationTargetException e) { throw new IllegalStateException(e.getCause()); } } /** * Look up a method in a class and set it to accessible. * See {@link #findMethodExact(String, ClassLoader, String, Object...)} for details. */ public static Method findMethodExact(Class clazz, String methodName, Object... parameterTypes) { return findMethodExact(clazz, methodName, getParameterClasses(clazz.getClassLoader(), parameterTypes)); } /** * Look up and return a method if it exists. * See {@link #findMethodExactIfExists(String, ClassLoader, String, Object...)} for details. */ public static Method findMethodExactIfExists(Class clazz, String methodName, Object... parameterTypes) { try { return findMethodExact(clazz, methodName, parameterTypes); } catch (IllegalStateException | NoSuchMethodError e) { return null; } } /** * Look up a method in a class and set it to accessible. * The method must be declared or overridden in the given class. *

* the method and parameter type resolution. * * @param className The name of the class which implements the method. * @param classLoader The class loader for resolving the target and parameter classes. * @param methodName The target method name. * @param parameterTypes The parameter types of the target method. * @return A reference to the method. * @throws NoSuchMethodError In case the method was not found. */ public static Method findMethodExact(String className, ClassLoader classLoader, String methodName, Object... parameterTypes) { return findMethodExact(findClass(className, classLoader), methodName, getParameterClasses(classLoader, parameterTypes)); } /** * Look up and return a method if it exists. * Like {@link #findMethodExact(String, ClassLoader, String, Object...)}, but doesn't throw an * exception if the method doesn't exist. * * @param className The name of the class which implements the method. * @param classLoader The class loader for resolving the target and parameter classes. * @param methodName The target method name. * @param parameterTypes The parameter types of the target method. * @return A reference to the method, or {@code null} if it doesn't exist. */ public static Method findMethodExactIfExists(String className, ClassLoader classLoader, String methodName, Object... parameterTypes) { try { return findMethodExact(className, classLoader, methodName, parameterTypes); } catch (IllegalStateException | NoSuchMethodError e) { return null; } } /** * Look up a method in a class and set it to accessible. * See {@link #findMethodExact(String, ClassLoader, String, Object...)} for details. *

*

This variant requires that you already have reference to all the parameter types. */ public static Method findMethodExact(Class clazz, String methodName, Class... parameterTypes) { String fullMethodName = clazz.getName() + '#' + methodName + getParametersString(parameterTypes) + "#exact"; if (methodCache.containsKey(fullMethodName)) { Method method = methodCache.get(fullMethodName); if (method == null) throw new NoSuchMethodError(fullMethodName); return method; } try { Method method = clazz.getDeclaredMethod(methodName, parameterTypes); method.setAccessible(true); methodCache.put(fullMethodName, method); return method; } catch (NoSuchMethodException e) { methodCache.put(fullMethodName, null); throw new NoSuchMethodError(fullMethodName); } } /** * Returns an array of all methods declared/overridden in a class with the specified parameter types. *

*

The return type is optional, it will not be compared if it is {@code null}. * Use {@code void.class} if you want to search for methods returning nothing. * * @param clazz The class to look in. * @param returnType The return type, or {@code null} (see above). * @param parameterTypes The parameter types. * @return An array with matching methods, all set to accessible already. */ public static Method[] findMethodsByExactParameters(Class clazz, Class returnType, Class... parameterTypes) { List result = new LinkedList<>(); for (Method method : clazz.getDeclaredMethods()) { if (returnType != null && returnType != method.getReturnType()) continue; Class[] methodParameterTypes = method.getParameterTypes(); if (parameterTypes.length != methodParameterTypes.length) continue; boolean match = true; for (int i = 0; i < parameterTypes.length; i++) { if (parameterTypes[i] != methodParameterTypes[i]) { match = false; break; } } if (!match) continue; method.setAccessible(true); result.add(method); } return result.toArray(new Method[result.size()]); } /** * Look up a method in a class and set it to accessible. *

*

This does'nt only look for exact matches, but for the best match. All considered candidates * must be compatible with the given parameter types, i.e. the parameters must be assignable * to the method's formal parameters. Inherited methods are considered here. * * @param clazz The class which declares, inherits or overrides the method. * @param methodName The method name. * @param parameterTypes The types of the method's parameters. * @return A reference to the best-matching method. * @throws NoSuchMethodError In case no suitable method was found. */ public static Method findMethodBestMatch(Class clazz, String methodName, Class... parameterTypes) { String fullMethodName = clazz.getName() + '#' + methodName + getParametersString(parameterTypes) + "#bestmatch"; if (methodCache.containsKey(fullMethodName)) { Method method = methodCache.get(fullMethodName); if (method == null) throw new NoSuchMethodError(fullMethodName); return method; } try { Method method = findMethodExact(clazz, methodName, parameterTypes); methodCache.put(fullMethodName, method); return method; } catch (NoSuchMethodError ignored) { } Method bestMatch = null; Class clz = clazz; boolean considerPrivateMethods = true; do { for (Method method : clz.getDeclaredMethods()) { // don't consider private methods of superclasses if (!considerPrivateMethods && Modifier.isPrivate(method.getModifiers())) continue; // compare name and parameters if (method.getName().equals(methodName) && isAssignable(parameterTypes, method.getParameterTypes(), true)) { // get accessible version of method if (bestMatch == null || MemberUtils.compareParameterTypes( method.getParameterTypes(), bestMatch.getParameterTypes(), parameterTypes) < 0) { bestMatch = method; } } } considerPrivateMethods = false; } while ((clz = clz.getSuperclass()) != null); if (bestMatch != null) { bestMatch.setAccessible(true); methodCache.put(fullMethodName, bestMatch); return bestMatch; } else { NoSuchMethodError e = new NoSuchMethodError(fullMethodName); methodCache.put(fullMethodName, null); throw e; } } /** * Look up a method in a class and set it to accessible. *

*

See {@link #findMethodBestMatch(Class, String, Class...)} for details. This variant * determines the parameter types from the classes of the given objects. */ public static Method findMethodBestMatch(Class clazz, String methodName, Object... args) { return findMethodBestMatch(clazz, methodName, getParameterTypes(args)); } /** * Look up a method in a class and set it to accessible. *

*

See {@link #findMethodBestMatch(Class, String, Class...)} for details. This variant * determines the parameter types from the classes of the given objects. For any item that is * {@code null}, the type is taken from {@code parameterTypes} instead. */ public static Method findMethodBestMatch(Class clazz, String methodName, Class[] parameterTypes, Object[] args) { Class[] argsClasses = null; for (int i = 0; i < parameterTypes.length; i++) { if (parameterTypes[i] != null) continue; if (argsClasses == null) argsClasses = getParameterTypes(args); parameterTypes[i] = argsClasses[i]; } return findMethodBestMatch(clazz, methodName, parameterTypes); } /** * Returns an array with the classes of the given objects. */ public static Class[] getParameterTypes(Object... args) { Class[] clazzes = new Class[args.length]; for (int i = 0; i < args.length; i++) { clazzes[i] = (args[i] != null) ? args[i].getClass() : null; } return clazzes; } /** * Retrieve classes from an array, where each element might either be a Class * already, or a String with the full class name. */ private static Class[] getParameterClasses(ClassLoader classLoader, Object[] parameterTypesAndCallback) { Class[] parameterClasses = null; for (int i = parameterTypesAndCallback.length - 1; i >= 0; i--) { Object type = parameterTypesAndCallback[i]; if (type == null) throw new IllegalStateException("parameter type must not be null", null); if (parameterClasses == null) parameterClasses = new Class[i + 1]; if (type instanceof Class) parameterClasses[i] = (Class) type; else if (type instanceof String) parameterClasses[i] = findClass((String) type, classLoader); else throw new IllegalStateException("parameter type must either be specified as Class or String", null); } // if there are no arguments for the method if (parameterClasses == null) parameterClasses = new Class[0]; return parameterClasses; } /** * Returns an array of the given classes. */ public static Class[] getClassesAsArray(Class... clazzes) { return clazzes; } private static String getParametersString(Class... clazzes) { StringBuilder sb = new StringBuilder("("); boolean first = true; for (Class clazz : clazzes) { if (first) first = false; else sb.append(","); if (clazz != null) sb.append(clazz.getCanonicalName()); else sb.append("null"); } sb.append(")"); return sb.toString(); } /** * Look up a constructor of a class and set it to accessible. * See {@link #findMethodExact(String, ClassLoader, String, Object...)} for details. */ public static Constructor findConstructorExact(Class clazz, Object... parameterTypes) { return findConstructorExact(clazz, getParameterClasses(clazz.getClassLoader(), parameterTypes)); } /** * Look up and return a constructor if it exists. * See {@link #findMethodExactIfExists(String, ClassLoader, String, Object...)} for details. */ public static Constructor findConstructorExactIfExists(Class clazz, Object... parameterTypes) { try { return findConstructorExact(clazz, parameterTypes); } catch (IllegalStateException | NoSuchMethodError e) { return null; } } /** * Look up a constructor of a class and set it to accessible. * See {@link #findMethodExact(String, ClassLoader, String, Object...)} for details. */ public static Constructor findConstructorExact(String className, ClassLoader classLoader, Object... parameterTypes) { return findConstructorExact(findClass(className, classLoader), getParameterClasses(classLoader, parameterTypes)); } /** * Look up and return a constructor if it exists. * See {@link #findMethodExactIfExists(String, ClassLoader, String, Object...)} for details. */ public static Constructor findConstructorExactIfExists(String className, ClassLoader classLoader, Object... parameterTypes) { try { return findConstructorExact(className, classLoader, parameterTypes); } catch (IllegalStateException | NoSuchMethodError e) { return null; } } /** * Look up a constructor of a class and set it to accessible. * See {@link #findMethodExact(String, ClassLoader, String, Object...)} for details. */ public static Constructor findConstructorExact(Class clazz, Class... parameterTypes) { String fullConstructorName = clazz.getName() + getParametersString(parameterTypes) + "#exact"; if (constructorCache.containsKey(fullConstructorName)) { Constructor constructor = constructorCache.get(fullConstructorName); if (constructor == null) throw new NoSuchMethodError(fullConstructorName); return constructor; } try { Constructor constructor = clazz.getDeclaredConstructor(parameterTypes); constructor.setAccessible(true); constructorCache.put(fullConstructorName, constructor); return constructor; } catch (NoSuchMethodException e) { constructorCache.put(fullConstructorName, null); throw new NoSuchMethodError(fullConstructorName); } } /** * Look up a class with the specified class loader. *

* There are various allowed syntaxes for the class name, but it's recommended to use one of *

* these: *
    *
  • {@code java.lang.String} *
  • {@code java.lang.String[]} (array) *
  • {@code android.app.ActivityThread.ResourcesKey} *
  • {@code android.app.ActivityThread$ResourcesKey} *
* * @param className The class name in one of the formats mentioned above. * @param classLoader The class loader, or {@code null} for the boot class loader. * @return A reference to the class. */ public static Class findClass(String className, ClassLoader classLoader) { if (classLoader == null) classLoader = ReflectUtil.class.getClassLoader(); try { return getClass(classLoader, className, false); } catch (ClassNotFoundException e) { throw new IllegalStateException(e); } } /** * Look up and return a class if it exists. * Like {@link #findClass}, but doesn't throw an exception if the class doesn't exist. * * @param className The class name. * @param classLoader The class loader, or {@code null} for the boot class loader. * @return A reference to the class, or {@code null} if it doesn't exist. */ public static Class findClassIfExists(String className, ClassLoader classLoader) { try { return findClass(className, classLoader); } catch (IllegalStateException e) { return null; } } /** * Look up a field in a class and set it to accessible. * * @param clazz The class which either declares or inherits the field. * @param fieldName The field name. * @return A reference to the field. * @throws NoSuchFieldError In case the field was not found. */ public static Field findField(Class clazz, String fieldName) { String fullFieldName = clazz.getName() + '#' + fieldName; if (fieldCache.containsKey(fullFieldName)) { Field field = fieldCache.get(fullFieldName); if (field == null) throw new NoSuchFieldError(fullFieldName); return field; } try { Field field = findFieldRecursiveImpl(clazz, fieldName); field.setAccessible(true); fieldCache.put(fullFieldName, field); return field; } catch (NoSuchFieldException e) { fieldCache.put(fullFieldName, null); throw new NoSuchFieldError(fullFieldName); } } /** * Look up and return a field if it exists. * Like {@link #findField}, but doesn't throw an exception if the field doesn't exist. * * @param clazz The class which either declares or inherits the field. * @param fieldName The field name. * @return A reference to the field, or {@code null} if it doesn't exist. */ public static Field findFieldIfExists(Class clazz, String fieldName) { try { return findField(clazz, fieldName); } catch (NoSuchFieldError e) { return null; } } private static Field findFieldRecursiveImpl(Class clazz, String fieldName) throws NoSuchFieldException { try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { while (true) { clazz = clazz.getSuperclass(); if (clazz == null || clazz.equals(Object.class)) break; try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException ignored) { } } throw e; } } /** * Returns the first field of the given type in a class. * Might be useful for Proguard'ed classes to identify fields with unique types. * * @param clazz The class which either declares or inherits the field. * @param type The type of the field. * @return A reference to the first field of the given type. * @throws NoSuchFieldError In case no matching field was not found. */ public static Field findFirstFieldByExactType(Class clazz, Class type) { Class clz = clazz; do { for (Field field : clz.getDeclaredFields()) { if (field.getType() == type) { field.setAccessible(true); return field; } } } while ((clz = clz.getSuperclass()) != null); throw new NoSuchFieldError("Field of type " + type.getName() + " in class " + clazz.getName()); } /** * Maps names of primitives to their corresponding primitive {@code Class}es. */ private static final Map> namePrimitiveMap = new HashMap<>(); static { namePrimitiveMap.put("boolean", Boolean.TYPE); namePrimitiveMap.put("byte", Byte.TYPE); namePrimitiveMap.put("char", Character.TYPE); namePrimitiveMap.put("short", Short.TYPE); namePrimitiveMap.put("int", Integer.TYPE); namePrimitiveMap.put("long", Long.TYPE); namePrimitiveMap.put("double", Double.TYPE); namePrimitiveMap.put("float", Float.TYPE); namePrimitiveMap.put("void", Void.TYPE); } /** * Maps primitive {@code Class}es to their corresponding wrapper {@code Class}. */ private static final Map, Class> primitiveWrapperMap = new HashMap<>(); static { primitiveWrapperMap.put(Boolean.TYPE, Boolean.class); primitiveWrapperMap.put(Byte.TYPE, Byte.class); primitiveWrapperMap.put(Character.TYPE, Character.class); primitiveWrapperMap.put(Short.TYPE, Short.class); primitiveWrapperMap.put(Integer.TYPE, Integer.class); primitiveWrapperMap.put(Long.TYPE, Long.class); primitiveWrapperMap.put(Double.TYPE, Double.class); primitiveWrapperMap.put(Float.TYPE, Float.class); primitiveWrapperMap.put(Void.TYPE, Void.TYPE); } /** * Maps a primitive class name to its corresponding abbreviation used in array class names. */ private static final Map abbreviationMap; /** * Maps an abbreviation used in array class names to corresponding primitive class name. */ private static final Map reverseAbbreviationMap; /** * Feed abbreviation maps */ static { final Map m = new HashMap<>(); m.put("int", "I"); m.put("boolean", "Z"); m.put("float", "F"); m.put("long", "J"); m.put("short", "S"); m.put("byte", "B"); m.put("double", "D"); m.put("char", "C"); final Map r = new HashMap<>(); for (final Map.Entry e : m.entrySet()) { r.put(e.getValue(), e.getKey()); } abbreviationMap = Collections.unmodifiableMap(m); reverseAbbreviationMap = Collections.unmodifiableMap(r); } /** * Maps wrapper {@code Class}es to their corresponding primitive types. */ private static final Map, Class> wrapperPrimitiveMap = new HashMap<>(); static { for (final Map.Entry, Class> entry : primitiveWrapperMap.entrySet()) { final Class primitiveClass = entry.getKey(); final Class wrapperClass = entry.getValue(); if (!primitiveClass.equals(wrapperClass)) { wrapperPrimitiveMap.put(wrapperClass, primitiveClass); } } } // ---------------------------------------------------------------------- /** * Converts a class name to a JLS style class name. * * @param className the class name * @return the converted name */ private static String toCanonicalName(String className) { className = deleteWhitespace(className); if (className == null) { throw new IllegalArgumentException("className must not be null."); } if (className.endsWith("[]")) { final StringBuilder classNameBuffer = new StringBuilder(); while (className.endsWith("[]")) { className = className.substring(0, className.length() - 2); classNameBuffer.append("["); } final String abbreviation = abbreviationMap.get(className); if (abbreviation != null) { classNameBuffer.append(abbreviation); } else { classNameBuffer.append("L").append(className).append(";"); } className = classNameBuffer.toString(); } return className; } /** *

Deletes all whitespaces from a String as defined by * {@link Character#isWhitespace(char)}. *

*
     * StringUtils.deleteWhitespace(null)         = null
     * StringUtils.deleteWhitespace("")           = ""
     * StringUtils.deleteWhitespace("abc")        = "abc"
     * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
     * 
* * @param str the String to delete whitespace from, may be null * @return the String without whitespaces, {@code null} if null String input */ public static String deleteWhitespace(final String str) { if (str == null || str.length() == 0) { return str; } final int sz = str.length(); final char[] chs = new char[sz]; int count = 0; for (int i = 0; i < sz; i++) { if (!Character.isWhitespace(str.charAt(i))) { chs[count++] = str.charAt(i); } } if (count == sz) { return str; } return new String(chs, 0, count); } /** * The package separator character: '.' == {@value}. */ public static final char PACKAGE_SEPARATOR_CHAR = '.'; /** * The inner class separator character: '$' == {@value}. */ public static final char INNER_CLASS_SEPARATOR_CHAR = '$'; /** * Returns the class represented by {@code className} using the * {@code classLoader}. This implementation supports the syntaxes * "{@code java.util.Map.Entry[]}", "{@code java.util.Map$Entry[]}", * "{@code [Ljava.util.Map.Entry;}", and "{@code [Ljava.util.Map$Entry;}". * * @param classLoader the class loader to use to load the class * @param className the class name * @param initialize whether the class must be initialized * @return the class represented by {@code className} using the {@code classLoader} * @throws ClassNotFoundException if the class is not found */ public static Class getClass( final ClassLoader classLoader, final String className, final boolean initialize) throws ClassNotFoundException { try { Class clazz; if (namePrimitiveMap.containsKey(className)) { clazz = namePrimitiveMap.get(className); } else { clazz = Class.forName(toCanonicalName(className), initialize, classLoader); } return clazz; } catch (final ClassNotFoundException ex) { // allow path separators (.) as inner class name separators final int lastDotIndex = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); if (lastDotIndex != -1) { try { return getClass(classLoader, className.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR_CHAR + className.substring(lastDotIndex + 1), initialize); } catch (final ClassNotFoundException ex2) { // NOPMD // ignore exception } } throw ex; } } public static boolean isSameLength(final Object[] array1, final Object[] array2) { return getLength(array1) == getLength(array2); } public static int getLength(final Object array) { if (array == null) { return 0; } return Array.getLength(array); } public static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; public static boolean isAssignable(Class[] classArray, Class[] toClassArray, final boolean autoboxing) { if (!isSameLength(classArray, toClassArray)) { return false; } if (classArray == null) { classArray = EMPTY_CLASS_ARRAY; } if (toClassArray == null) { toClassArray = EMPTY_CLASS_ARRAY; } for (int i = 0; i < classArray.length; i++) { if (!isAssignable(classArray[i], toClassArray[i], autoboxing)) { return false; } } return true; } public static Class wrapperToPrimitive(final Class cls) { return wrapperPrimitiveMap.get(cls); } public static Class primitiveToWrapper(final Class cls) { Class convertedClass = cls; if (cls != null && cls.isPrimitive()) { convertedClass = primitiveWrapperMap.get(cls); } return convertedClass; } public static boolean isAssignable(Class cls, final Class toClass, final boolean autoboxing) { if (toClass == null) { return false; } // have to check for null, as isAssignableFrom doesn't if (cls == null) { return !toClass.isPrimitive(); } //autoboxing: if (autoboxing) { if (cls.isPrimitive() && !toClass.isPrimitive()) { cls = primitiveToWrapper(cls); if (cls == null) { return false; } } if (toClass.isPrimitive() && !cls.isPrimitive()) { cls = wrapperToPrimitive(cls); if (cls == null) { return false; } } } if (cls.equals(toClass)) { return true; } if (cls.isPrimitive()) { if (!toClass.isPrimitive()) { return false; } if (Integer.TYPE.equals(cls)) { return Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Long.TYPE.equals(cls)) { return Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Boolean.TYPE.equals(cls)) { return false; } if (Double.TYPE.equals(cls)) { return false; } if (Float.TYPE.equals(cls)) { return Double.TYPE.equals(toClass); } if (Character.TYPE.equals(cls)) { return Integer.TYPE.equals(toClass) || Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Short.TYPE.equals(cls)) { return Integer.TYPE.equals(toClass) || Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } if (Byte.TYPE.equals(cls)) { return Short.TYPE.equals(toClass) || Integer.TYPE.equals(toClass) || Long.TYPE.equals(toClass) || Float.TYPE.equals(toClass) || Double.TYPE.equals(toClass); } // should never get here return false; } return toClass.isAssignableFrom(cls); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy