zoukankan      html  css  js  c++  java
  • Java反射用法以及isAssignableFrom()方法与instanceof关键字用法

    这是从若依框架获取的代码

      /**
         * 判断是否需要过滤的对象。
         * 
         * @param o 对象信息。
         * @return 如果是需要过滤的对象,则返回true;否则返回false。
         */
        @SuppressWarnings("rawtypes")
        public boolean isFilterObject(final Object o)
        {
            Class<?> clazz = o.getClass();
            if (clazz.isArray())
            {
                return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
            }
            else if (Collection.class.isAssignableFrom(clazz))
            {
                Collection collection = (Collection) o;
                for (Iterator iter = collection.iterator(); iter.hasNext();)
                {
                    return iter.next() instanceof MultipartFile;
                }
            }
            else if (Map.class.isAssignableFrom(clazz))
            {
                Map map = (Map) o;
                for (Iterator iter = map.entrySet().iterator(); iter.hasNext();)
                {
                    Map.Entry entry = (Map.Entry) iter.next();
                    return entry.getValue() instanceof MultipartFile;
                }
            }
            return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
                    || o instanceof BindingResult;
        }
    }

    isAssignableFrom()方法与instanceof关键字的区别总结为以下两个点:

    • isAssignableFrom()方法是从类继承的角度去判断,instanceof关键字是从实例继承的角度去判断。
    • isAssignableFrom()方法是判断是否为某个类的父类,instanceof关键字是判断是否某个类的子类。

    使用方法:

    父类.class.isAssignableFrom(子类.class)
    
    子类实例 instanceof 父类类型

    isAssignableFrom()方法的调用者和参数都是Class对象,调用者为父类,参数为本身或者其子类。

    instanceof关键字两个参数,前一个为类的实例,后一个为其本身或者父类的类型。

    我们有时候需要为对象字段设置默认值,即在别的处理中生成对象并对对象进行赋值后,有些值需要有默认值,但是又不方便通过构造方法设置的时候,我们可以通过反射配合注解来为其设置默认值而不用调用一堆set方法。

    下面这个例子即反射配置注解为对象字段设置默认值(包括父类),仅支持String和本类型的包装部分包装类(Number的子类)。
    首先定义注解:

    /**
     * description:
     *
     * @author wkGui
     */
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface ParamDefaultValue {
        String value();
    }

    定义注解的解析类:

    /**
     * description:
     *
     * @author wkGui
     */
    public class ParamProcessor {
        public static void applyDefaultValue(Object o) {
            Class sourceClass = o.getClass();
            //获取对象所有字段 包括父类
            ArrayList<Field> fields = new ArrayList<>();
            while (sourceClass != null){
                fields.addAll(Arrays.asList(sourceClass.getDeclaredFields()));
                sourceClass = sourceClass.getSuperclass();
            }
    
            for (Field field : fields) {
                field.setAccessible(true);
                if (field.isAnnotationPresent(ParamDefaultValue.class)) {
                    try {
                        Object val = field.get(o);
                        if (val != null) {
                            continue;
                        }
                        Class type = field.getType();
                        if (type.isPrimitive()) {
                            continue;
                        }
                        String defVal = field.getAnnotation(ParamDefaultValue.class).value();
    
                        if (String.class.isAssignableFrom(type)) {
                            field.set(o, defVal);
                        } else if (Number.class.isAssignableFrom(type)) {
                            if (Byte.class.isAssignableFrom(type)) {
                                field.set(o, Byte.valueOf(defVal));
                            } else if (Float.class.isAssignableFrom(type)) {
                                field.set(o, Float.valueOf(defVal));
                            } else if (Short.class.isAssignableFrom(type)) {
                                field.set(o, Short.valueOf(defVal));
                            } else if (Integer.class.isAssignableFrom(type)) {
                                field.set(o, Integer.valueOf(defVal));
                            } else if (Double.class.isAssignableFrom(type)) {
                                field.set(o, Double.valueOf(defVal));
                            } else if (Long.class.isAssignableFrom(type)) {
                                field.set(o, Long.valueOf(defVal));
                            }
                        }
    
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.util.Date;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.commons.lang3.Validate;
    import org.apache.poi.ss.usermodel.DateUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
     * 
     * @author test
     */
    @SuppressWarnings("rawtypes")
    public class ReflectUtils
    {
        private static final String SETTER_PREFIX = "set";
    
        private static final String GETTER_PREFIX = "get";
    
        private static final String CGLIB_CLASS_SEPARATOR = "$$";
    
        private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
    
        /**
         * 调用Getter方法.
         * 支持多级,如:对象名.对象名.方法
         */
        @SuppressWarnings("unchecked")
        public static <E> E invokeGetter(Object obj, String propertyName)
        {
            Object object = obj;
            for (String name : StringUtils.split(propertyName, "."))
            {
                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
                object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
            }
            return (E) object;
        }
    
        /**
         * 调用Setter方法, 仅匹配方法名。
         * 支持多级,如:对象名.对象名.方法
         */
        public static <E> void invokeSetter(Object obj, String propertyName, E value)
        {
            Object object = obj;
            String[] names = StringUtils.split(propertyName, ".");
            for (int i = 0; i < names.length; i++)
            {
                if (i < names.length - 1)
                {
                    String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
                    object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
                }
                else
                {
                    String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
                    invokeMethodByName(object, setterMethodName, new Object[] { value });
                }
            }
        }
    
        /**
         * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
         */
        @SuppressWarnings("unchecked")
        public static <E> E getFieldValue(final Object obj, final String fieldName)
        {
            Field field = getAccessibleField(obj, fieldName);
            if (field == null)
            {
                logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
                return null;
            }
            E result = null;
            try
            {
                result = (E) field.get(obj);
            }
            catch (IllegalAccessException e)
            {
                logger.error("不可能抛出的异常{}", e.getMessage());
            }
            return result;
        }
    
        /**
         * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
         */
        public static <E> void setFieldValue(final Object obj, final String fieldName, final E value)
        {
            Field field = getAccessibleField(obj, fieldName);
            if (field == null)
            {
                // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
                logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
                return;
            }
            try
            {
                field.set(obj, value);
            }
            catch (IllegalAccessException e)
            {
                logger.error("不可能抛出的异常: {}", e.getMessage());
            }
        }
    
        /**
         * 直接调用对象方法, 无视private/protected修饰符.
         * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
         * 同时匹配方法名+参数类型,
         */
        @SuppressWarnings("unchecked")
        public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
                final Object[] args)
        {
            if (obj == null || methodName == null)
            {
                return null;
            }
            Method method = getAccessibleMethod(obj, methodName, parameterTypes);
            if (method == null)
            {
                logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
                return null;
            }
            try
            {
                return (E) method.invoke(obj, args);
            }
            catch (Exception e)
            {
                String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
                throw convertReflectionExceptionToUnchecked(msg, e);
            }
        }
    
        /**
         * 直接调用对象方法, 无视private/protected修饰符,
         * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
         * 只匹配函数名,如果有多个同名函数调用第一个。
         */
        @SuppressWarnings("unchecked")
        public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args)
        {
            Method method = getAccessibleMethodByName(obj, methodName, args.length);
            if (method == null)
            {
                // 如果为空不报错,直接返回空。
                logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
                return null;
            }
            try
            {
                // 类型转换(将参数数据类型转换为目标方法参数类型)
                Class<?>[] cs = method.getParameterTypes();
                for (int i = 0; i < cs.length; i++)
                {
                    if (args[i] != null && !args[i].getClass().equals(cs[i]))
                    {
                        if (cs[i] == String.class)
                        {
                            args[i] = Convert.toStr(args[i]);
                            if (StringUtils.endsWith((String) args[i], ".0"))
                            {
                                args[i] = StringUtils.substringBefore((String) args[i], ".0");
                            }
                        }
                        else if (cs[i] == Integer.class)
                        {
                            args[i] = Convert.toInt(args[i]);
                        }
                        else if (cs[i] == Long.class)
                        {
                            args[i] = Convert.toLong(args[i]);
                        }
                        else if (cs[i] == Double.class)
                        {
                            args[i] = Convert.toDouble(args[i]);
                        }
                        else if (cs[i] == Float.class)
                        {
                            args[i] = Convert.toFloat(args[i]);
                        }
                        else if (cs[i] == Date.class)
                        {
                            if (args[i] instanceof String)
                            {
                                args[i] = DateUtils.parseDate(args[i]);
                            }
                            else
                            {
                                args[i] = DateUtil.getJavaDate((Double) args[i]);
                            }
                        }
                        else if (cs[i] == boolean.class || cs[i] == Boolean.class)
                        {
                            args[i] = Convert.toBool(args[i]);
                        }
                    }
                }
                return (E) method.invoke(obj, args);
            }
            catch (Exception e)
            {
                String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
                throw convertReflectionExceptionToUnchecked(msg, e);
            }
        }
    
        /**
         * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
         * 如向上转型到Object仍无法找到, 返回null.
         */
        public static Field getAccessibleField(final Object obj, final String fieldName)
        {
            // 为空不报错。直接返回 null
            if (obj == null)
            {
                return null;
            }
            Validate.notBlank(fieldName, "fieldName can't be blank");
            for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
            {
                try
                {
                    Field field = superClass.getDeclaredField(fieldName);
                    makeAccessible(field);
                    return field;
                }
                catch (NoSuchFieldException e)
                {
                    continue;
                }
            }
            return null;
        }
    
        /**
         * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
         * 如向上转型到Object仍无法找到, 返回null.
         * 匹配函数名+参数类型。
         * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
         */
        public static Method getAccessibleMethod(final Object obj, final String methodName,
                final Class<?>... parameterTypes)
        {
            // 为空不报错。直接返回 null
            if (obj == null)
            {
                return null;
            }
            Validate.notBlank(methodName, "methodName can't be blank");
            for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
            {
                try
                {
                    Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
                    makeAccessible(method);
                    return method;
                }
                catch (NoSuchMethodException e)
                {
                    continue;
                }
            }
            return null;
        }
    
        /**
         * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
         * 如向上转型到Object仍无法找到, 返回null.
         * 只匹配函数名。
         * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
         */
        public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
        {
            // 为空不报错。直接返回 null
            if (obj == null)
            {
                return null;
            }
            Validate.notBlank(methodName, "methodName can't be blank");
            for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
            {
                Method[] methods = searchType.getDeclaredMethods();
                for (Method method : methods)
                {
                    if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
                    {
                        makeAccessible(method);
                        return method;
                    }
                }
            }
            return null;
        }
    
        /**
         * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
         */
        public static void makeAccessible(Method method)
        {
            if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
                    && !method.isAccessible())
            {
                method.setAccessible(true);
            }
        }
    
        /**
         * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
         */
        public static void makeAccessible(Field field)
        {
            if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
                    || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
            {
                field.setAccessible(true);
            }
        }
    
        /**
         * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
         * 如无法找到, 返回Object.class.
         */
        @SuppressWarnings("unchecked")
        public static <T> Class<T> getClassGenricType(final Class clazz)
        {
            return getClassGenricType(clazz, 0);
        }
    
        /**
         * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
         * 如无法找到, 返回Object.class.
         */
        public static Class getClassGenricType(final Class clazz, final int index)
        {
            Type genType = clazz.getGenericSuperclass();
    
            if (!(genType instanceof ParameterizedType))
            {
                logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
                return Object.class;
            }
    
            Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
    
            if (index >= params.length || index < 0)
            {
                logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
                        + params.length);
                return Object.class;
            }
            if (!(params[index] instanceof Class))
            {
                logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
                return Object.class;
            }
    
            return (Class) params[index];
        }
    
        public static Class<?> getUserClass(Object instance)
        {
            if (instance == null)
            {
                throw new RuntimeException("Instance must not be null");
            }
            Class clazz = instance.getClass();
            if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
            {
                Class<?> superClass = clazz.getSuperclass();
                if (superClass != null && !Object.class.equals(superClass))
                {
                    return superClass;
                }
            }
            return clazz;
    
        }
    
        /**
         * 将反射时的checked exception转换为unchecked exception.
         */
        public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
        {
            if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
                    || e instanceof NoSuchMethodException)
            {
                return new IllegalArgumentException(msg, e);
            }
            else if (e instanceof InvocationTargetException)
            {
                return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
            }
            return new RuntimeException(msg, e);
        }
    }

    参考链接:

    https://blog.csdn.net/qq_36666651/article/details/81215221

  • 相关阅读:
    Hackthebox 渗透测试笔记-popcorn[linux提权]
    HTB 渗透测试笔记-Devel[msvenom][提权]
    HTB 渗透测试笔记-Legacy
    Hackthebox网络不稳定的解决方案
    eslint 常用配置
    第十课之培训课程总结
    第九课 复习之从零开始搭建页面
    第八课之提高开发效率的es6以及函数
    第七课之dva以及前后端交互
    第六课之antd以及组件开发介绍
  • 原文地址:https://www.cnblogs.com/xiaohuasan/p/14929655.html
Copyright © 2011-2022 走看看