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;
    }
相關文章
相關標籤/搜索