1,什麼是Java的反射?
經過對象所屬類的Class對象,能夠動態獲取運行時對象的信息,或執行對象的方法。java
2,Class對象是什麼?
每個類在JVM中都對應惟一一個java.lang.Class對象,能夠經過newInstance()來調用無參構造建立一個實例對象。程序員
// 獲取類加載器 ClassLoader getClassLoader() // 獲取父類 Class<? super T> getSuperclass() // 獲取繼承父類時標明的泛型信息 Type getGenericSuperclass() // 獲取該類實現的接口 Class<?>[] getInterfaces() // 獲取實現父接口時標明的泛型信息 Type[] getGenericInterfaces() // 獲取全部屬性 Field[] getFields() // 獲取當前類及全部繼承的父類的public修飾的方法。僅包括public Method[]getMethods() // 獲取當前類的全部方法,包括public/private/protected/default修飾的方法,不包括繼承來的 Method[] getDeclaredMethods() // 獲取全部構造方法 Constructor<?>[] getConstructors() // 獲取具體名稱的屬性 Field getField(String name) // 獲取具體的方法,僅包括public Method getMethod(String name, Class<?>... parameterTypes) // 獲取具體的方法,包括public/private/protected/default修飾的方法,不包括繼承來的 Method getDeclaredMethod(String name, Class<?>... parameterTypes) // 獲取具體的構造方法 Constructor<T> getConstructor(Class<?>... parameterTypes) // 是否被指定註解修飾 boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) // 獲取全部類的註解 Annotation[] getAnnotations() // 獲取指定的註解 <A extends Annotation> A getAnnotation(Class<A> annotationClass) // 獲取指定的註解數組,包括繼承父類的。JDK1.8支持,與@Repeatable()相關 <A extends Annotation> A getAnnotationsByType(Class<A> annotationClass) // 獲取指定的註解數組,不包括繼承父類的。JDK1.8支持,與@Repeatable()相關 <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) // 獲取修飾符 int getModifiers() // 獲取全類名 String getName() // 獲取簡稱 String getSimpleName() // 判斷是不是接口 boolean isInterface() // 判斷obj是不是該class的實例對象 boolean isInstance(Object obj)
3,如何獲取Class對象?spring
4,Method對象是什麼
Method對象表示Class中的方法信息。express
// 獲取單獨的方法名稱 String getName() // 獲取完整的方法信息(包括修飾符、返回值、路徑、名稱、參數、拋出值) String toGenericString() // 獲取修飾符 int getModifiers() // 獲取參數類型信息 Class<?>[] getParameterTypes() // 獲取方法參數的泛型信息 Type[] getGenericParameterTypes() // 獲取返回類型信息 Class<?> getReturnType() // 獲取方法返回值的泛型信息 Type getGenericReturnType() // 獲取異常信息 Class<?>[] getExceptionTypes() // 是否被指定註解修飾 boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) // 獲取方法註解 Annotation[] getAnnotations() // 獲取指定的註解 <T extends Annotation> T getAnnotation(Class<T> annotationClass) // 獲取方法參數的全部註解 Annotation[][] getParameterAnnotations() // 獲取指定的註解數組,包括繼承父類的。JDK1.8支持,與@Repeatable()相關 <T extends Annotation> T[] getAnnotationsByType(Class<A> annotationClass) // 獲取指定的註解數組,不包括繼承父類的。JDK1.8支持,與@Repeatable()相關 <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<A> annotationClass) // 是不是橋接方法。JDK 1.5 引入泛型後,爲了使Java的泛型方法生成的字節碼和 1.5 版本前的字節碼相兼容,由編譯器自動生成的方法 boolean isBridge() // 是不是默認方法。JDK1.8開始接口容許有默認方法 boolean isDefault() // 是不是可變參方法。JDK1.5開始支持方法入參能夠是可變參 boolean isVarArgs() // 是不是合成方法。JDK1.5開始支持枚舉類,這種類型不是程序員寫的,是編譯器生成的。涉及枚舉類的地方會由編譯器生成一些該類型方法 boolean isSynthetic() // 反射執行obj對象的該方法,參數爲args Object invoke(Object obj, Object... args)
5,Field對象是什麼?
Field對象表示Class中的屬性信息。數組
// 獲取屬性名 String getName() // 獲取修飾符 int getModifiers() // 是不是枚舉類型 boolean isEnumConstant() // 是不是合成類型 boolean isSynthetic() // 獲取屬性類型 Class<?>getType() // 獲取屬性的泛型信息 Type getGenericType() // 獲取obj對象的當前屬性值 Object get(Object obj) // 將obj對象的當前屬性設置爲value void set(Object obj, Object value) // 是否被指定註解修飾 boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) // 獲取屬性的全部註解 Annotation[] getAnnotations() // 獲取屬性上的指定類型的註解 <T extends Annotation> T getAnnotation(Class<T> annotationClass) // 獲取指定的註解數組,包括繼承父類的。JDK1.8支持,與@Repeatable()相關 <T extends Annotation> T[] getAnnotationsByType(Class<A> annotationClass) // 獲取指定的註解數組,不包括繼承父類的。JDK1.8支持,與@Repeatable()相關 <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<A> annotationClass)
6,其餘好比Package對象,Constructor對象,URL對象,在反射中的使用頻率小,這裏就不研究了。.net
注意:code
因爲編譯會進行泛型擦除致使編譯後的字節碼是沒有泛型信息的,因此運行期沒法經過反射獲得泛型信息。對象
訪問private的方法和變量須要設置method.setAccessible(true)或field.setAccessible(true)。blog
invoke()執行方法時方法的參數類型及順序要正確。繼承
如何經過橋接方法獲取對應的實際方法呢?能夠查看spring中org.springframework.core.BridgeMethodResolver
類的源碼。其實是經過判斷方法名、參數的個數以及泛型類型參數來獲取的。
反射get和set的3種方式:
java.beans.PropertyDescriptor
private Object getValueByReflect(Object obj, String expression) throws NoSuchFieldException, SecurityException, IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class<? extends Object> clazz = obj.getClass(); Field field = clazz.getDeclaredField(expression); PropertyDescriptor pd=new PropertyDescriptor(field.getName(),clazz); Method method = pd.getReadMethod(); return method.invoke(obj); }
參考資料: