內省是基於反射實現的,主要用來操做JavaBean,經過內省能夠很方便的動態得到bean的set/get方法,屬性,方法名,他至關因而反射的工具類同樣java
反射其實簡單來講就是經過類的名字得到對於這個類的描述,這種描述包括方法、構造器、屬性的描述。舉個例子來講就是經過類名能夠進行實例化對象、對類中的方法的調用、對類中屬性的賦值。在許多的框架中反射是常常被應用到的技術,下面舉個利用反射進行對象A的屬性賦值到對象B。api
詳細的反射詳解,能夠看不學無數——初識反射框架
其中A屬性以下ide
public class A { private String a; private String b; ---------get.set方法 }
其中B屬性以下,B是繼承A的。因此B中也有A種a、b兩個變量工具
public class B extends A{ private String c; private String d; ---------get.set方法 }
將A中a、b屬性的值賦值給B中的a、b兩個屬性ui
public class IntrospectorAndReflect { public static void main(String[] args) throws Exception { Class classA = Class.forName("Practice.Day05.A"); -- 得到A的Class對象 Class classB = Class.forName("Practice.Day05.B"); -- 得到B的Class對象 A a = (A) classA.newInstance(); -- 實例化A對象 B b = (B) classB.newInstance(); -- 實例化B對象 a.setA("a"); a.setB("b"); fatherToChild(a,b); System.out.println(b.getA()); } public static <T>void fatherToChild(T father,T child) throws Exception { if (child.getClass().getSuperclass()!=father.getClass()){ throw new Exception("child 不是 father 的子類"); } Class<?> fatherClass = father.getClass(); --經過反射得到Class對象 Field[] declaredFields = fatherClass.getDeclaredFields(); --得到此Class對象的屬性信息 for (int i = 0; i < declaredFields.length; i++) { Field field=declaredFields[i]; //得到屬性的get方法 Method method=fatherClass.getDeclaredMethod("get"+upperHeadChar(field.getName())); Object obj = method.invoke(father); field.setAccessible(true);--解除方法的私有限定 field.set(child,obj);--執行set方法 } } /** * 首字母大寫,in:deleteDate,out:DeleteDate */ public static String upperHeadChar(String in) { String head = in.substring(0, 1); String out = head.toUpperCase() + in.substring(1, in.length()); return out; } }
上面演示瞭如何經過類的全路徑名得到類的Class對象,而且將Class對象進行實例化類的過程。其實這就是反射。其實有時候咱們會想,直接new一個對象這麼簡單的事情,何須要用反射這麼麻煩呢?由於反射最大的應用就是動態加載。舉個簡單的例子以下,如今有A、B兩個類,根據運行的須要進行加載不一樣的類code
if (條件1) 加載A類 if (條件2) 加載B類
運行時肯定類型,綁定對象。動態編譯最大限度地發揮了Java的靈活性,體現了多態的應用,能夠減低類之間的耦合性。orm
內省是什麼?咱們能夠看關於java api文檔中的介紹對象
The Introspector class provides a standard way for tools to learn about the properties, events, and methods supported by a target Java Bean.繼承
For each of those three kinds of information, the Introspector will separately analyze the bean's class and superclasses looking for either explicit or implicit information and use that information to build a BeanInfo object that comprehensively describes the target bean.
簡單理解就是內省是對於java Bean
的缺省處理,既好比在一個實體類中,有nama、address屬性,那麼系統會默認在此類中會有get/set方法進行得到和設置這兩個值的方法。而且經過上面的介紹能夠得知,內省是經過BeanInfo
類進行操做類中的屬性和方法的。實例以下:
public class IntrospectorDemo { public static void main(String[] args) throws IntrospectionException { BeanInfo beanInfo = Introspector.getBeanInfo(A.class); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors(); BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor(); for (PropertyDescriptor x:propertyDescriptors){ System.out.println(x.getName()); System.out.println(x.getReadMethod()); } System.out.println("-----------------------"); for (MethodDescriptor y:methodDescriptors){ System.out.println(y.getName()); } } }
能夠想成內省是對於反射的更一層的封裝,讓咱們更加容易的獲得類的信息而且操做它
在內省中經常使用的類有四個
Introspector
:將JavaBean中
的屬性封裝起來進行操做。在程序把一個類當作JavaBean
來看,就是調用Introspector.getBeanInfo()
方法,獲得的BeanInfo
對象封裝了把這個類當作JavaBean
看的結果信息,即屬性的信息BeanInfo
:將類中的信息封裝到BeanInfo
類中,得到了BeanInfo
對象就至關於得到了類中的全部屬性信息。調用getPropertyDescriptors()
方法得到屬性描述器,即得到了全部的屬性信息。調用PropertyDescriptor
:PropertyDescriptor
實例封裝了每一個屬性特有的一些性質,好比調用getReadMethod()
方法就能得到這個屬性的get方法Method,調用getWriteMethod()
方法就能得到這個屬性的set方法Method。