Reflect

每一个类被加载后(类文件常量池),  JVM就会为该类生成一个对应的 Class 对象(运行时常量池), 经过该 Class 对象就能够访问到 JVM 中的这个类 。java

Java 程序中得到Class 对象一般有以下三种方式:
     1. 使用 Class 的 forName() 静态方法
     2. 调用某个类的 class 属性 (无须调用方法, 性能更好)
     3. 调用某个对象的 getClass() 方法数组

错误的使用方法

每次须要获取Class的对象时都使用Class.forName方法,或者在须要调用Class对象上的方法时都调用getDeclaredMethod(String name, Class<?>... parameterTypes)或getMethod(String name, Class<?>... parameterTypes)方法获取Method对象,再调用其上的invoke(Object obj, Object... args)方法。缓存

这里存在两个容易形成性能损耗的地方:函数

  • Class.forName方法的调用会执行Class类文件在整个类路径下的搜索,频繁调用比较影响性能。
  • Class对象上的getDeclaredMethod (String, Class<?>...)或getMethod(String, Class<?>...)方法的会循环执行在Class对象上的Method对象集合搜索(只复制查找到的对象); getMethods()还会执行方法Method对象集合的Copy, 比直接使用getMethod(String, Class<?>...)方法还要消耗时间及空间。
public Method[] getMethods() throws SecurityException {
        checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
        return copyMethods(privateGetPublicMethods());
    }

    public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
        Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
        if (method == null) {
            throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
        }
        return method;
    }

    private static Method searchMethods(Method[] methods,
                                        String name,
                                        Class<?>[] parameterTypes)
    {
        Method res = null;
        String internedName = name.intern();
        for (int i = 0; i < methods.length; i++) {
            Method m = methods[i];
            if (m.getName() == internedName
                && arrayContentsEq(parameterTypes, m.getParameterTypes())
                && (res == null
                    || res.getReturnType().isAssignableFrom(m.getReturnType())))
                res = m;
        }

        return (res == null ? res : getReflectionFactory().copyMethod(res));
    }

一般: 将须要的反射的结果给缓存下来,避免屡次对类(方法、属性)信息屡次加载类信息并full查询,精确指定查找方式效率高于遍历查找性能

Class类常见的方法

  1. newInstance() :建立此 Class 对象所表示的类的一个新实例。
  2. isPrimitive() :断定指定的 Class 对象是否表示一个基本类型。
  3. isArray() :断定此 Class 对象是否表示一个数组类。
  4. getPackage() :获取此类的包。
  5. getName() :以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
  6. getInterfaces() :肯定此对象所表示的类或接口实现的接口。
  7. forName(String className) :返回与带有给定字符串名的类或接口相关联的 Class 对象
  8. setAccessible(true) :并非将方法(属性)的访问权限改为了public,而是取消java的权限控制检查。因此即便是public方法,其accessible 属性默认也是false
  9. Class.getFields()只能访问类中声明为公有的字段,私有的字段它没法访问,能访问从其它类继承来的公有字段(Field.get 调用target)
  10. Class. getDeclaredFields()能访问类中全部的字段,与public、private、protected无关不能访问从其它类继承来的字段
  11. Class.getMethods(): 只能访问类中声明为公有的方法,私有的方法它没法访问,能访问从其它类继承来的公有方法。(Method.invoke 调用target)
    (实现: 在privateGetPublicMethods()方法中循环获取superclass的public方法: getDeclaredMethods0(true))
  12. Class.getDeclaredFields() :能访问类中全部的字段,与public、private、protected无关,不能访问从其它类继承来的方法。
    (实现:在privateGetPublicMethods(false)方法中会获取当前class的方法: getDeclaredMethods0(false))
  13. getConstructors():只能访问类中声明为public的构造函数。
  14. getDeclaredConstructors():能访问类中全部的构造函数,与public、private、protected无关。
  15. obj  instanceof 类名: 自身或子类实例 instanceof 自身类名   用于对象引用变量,检查左边的被测试对象是否是右边类或接口的( 或其子类子接口 )实例化。若是被测对象是null值,则测试结果为false。   
  16. Class.isInstance(Object obj) : 自身类.class.isInstance(自身或子类实例)   obj是被测试的对象,若是obj是调用这个方法的class或接口的实例,则返回true。这个方法是instanceof运算符的动态等价。
  17. Class.isAssignableFrom(Class cls): 自身类.class.isAssignableFrom(自身类或子类.class)  若是调用这个方法的class或接口与参数cls表示的类或接口相同,或者是参数cls表示的类或接口的父类,则返回true。  
public static String getValue(String property, Object o) {
        String res = "";
        try {
            Method m = o.getClass().getMethod("get" + toFirstUp(property));
            Object value = m.invoke(o);
            res = (value == null ? "" : value.toString());
        } catch (Exception e) {
            logger.error(e, "getValue err");
       }

        return res;
    }


public static void setValue(String value, String property, Object o) {
        try {
            Method[] ms = o.getClass().getMethods();
            for (Method m : ms) {
                if (m.getName().equals("set" + toFirstUp(property))) {
                    m.invoke(o, new Object[] { value });
                    break;
                }
            }
        } catch (Exception e) {
            logger.error(e, "setValue err");
        }

}


public static List<ValidateResult> validateAll(BaseValidate v) throws Exception {

        List<ValidateResult> list = new ArrayList<ValidateResult>();

        Field[] fields = v.getClass().getDeclaredFields();
        Map<Class, BaseVal> valMap = BaseVal.getValMap();

        for (Field f : fields) {

            f.setAccessible(true);

            Annotation[] as = f.getAnnotations();

            if (as != null && as.length > 0) {
                for (Annotation a : as) {
                    BaseVal val = valMap.get(a.annotationType());

                    if (val != null) {
                        ValidateResult result = val.validate(f.get(v), f, a);

                        if (!result.isSucc()) {
                            list.add(result);
                        }
                    }
                }
            }
        }

        return list;
    }
相关文章
相关标签/搜索