java 反射调用方法_java的反射机制,以及通过反射获取方法,变量等操作
我們應(yīng)用會(huì)用到反射這個(gè)知識(shí)點(diǎn),肯定是想要在運(yùn)行時(shí)得到類的信息,根據(jù)類的那些信息去做一些特定的操作。那么,首先無(wú)疑就是得到類的信息,在JDK中提供了Class對(duì)象來(lái)保存類的信息。所以,反射的第一步就是得到Class對(duì)象。在JDK中提供了兩種方式得到Class對(duì)象。第一種,如果編寫(xiě)代碼的時(shí)候,就知道Class的名字,可以直接用如下方式得到Class對(duì)象:
//第一種,如果編寫(xiě)代碼的時(shí)候,就知道Class的名字,可以直接用如下方式得到Class對(duì)象:Class exampleObjectClass = ExampleObject.class;//第二種,如果在編寫(xiě)代碼的時(shí)候,不知道類的名字,但是在運(yùn)行時(shí)的時(shí)候,可以得到一個(gè)類名的字符串,可以用如下的方式獲取Class對(duì)象://注意,此方法需要有2個(gè)條件,第一,forName中的字符串必須是全限定名,第二,//這個(gè)Class類必須在classpath的路徑下面,因?yàn)樵摲椒〞?huì)拋出ClassNotFoundException的異常。Class exampleObjectClass2 = Class.forName("com.team.frame.fanshe.ExampleObject");
下面介紹通過(guò)反射可以獲取那些信息:
1. 得到類的名字
/*** 得到類的名字* 類的名字有兩種方式得到,一種是getName(),一種是getSimpleName()。* 第一種得到的是全限定名,第二種得到的是這個(gè)類的名字,不帶包名。看下面的例子:Class對(duì)象,已經(jīng)通過(guò)上面的代碼得到了。*/String fullClassName = exampleObjectClass.getName();String simpleClassName = exampleObjectClass.getSimpleName();System.out.println(fullClassName);System.out.println(simpleClassName);2. 得到類的包名、父類和實(shí)現(xiàn)的接口
//得到包信息Package aPackage = exampleObjectClass.getPackage();System.out.println(aPackage);//得到父類Class superClass = exampleObjectClass.getSuperclass();System.out.println(superClass.getSimpleName());//判斷父類是否是抽象類boolean abstract1 = Modifier.isAbstract(superClass.getModifiers());//我們還可以得到父類實(shí)現(xiàn)的接口Class[] interfaces = superClass.getInterfaces();System.out.println("父類的接口" + interfaces[0]);3. 利用Java反射可以得到一個(gè)類的構(gòu)造器,并根據(jù)構(gòu)造器,在運(yùn)行時(shí)動(dòng)態(tài)的創(chuàng)建一個(gè)對(duì)象
Constructor[] constructors = exampleObjectClass.getConstructors();for(Constructor cos:constructors){System.out.println(cos.toString());}//如果,事先知道要訪問(wèn)的構(gòu)造方法的參數(shù)類型,可以利用如下方法獲取指定的構(gòu)造方法,例子如下:Constructor constructor = exampleObjectClass.getConstructor(String.class);System.out.println(constructor);//此外,如果我們不知道構(gòu)造器的參數(shù),只能得到所有的構(gòu)造器對(duì)象,那么可以用如下方式得到每一個(gè)構(gòu)造器對(duì)想的參數(shù):Constructor[] constructors2 = exampleObjectClass.getConstructors();for(Constructor cos2:constructors2){Class[] parameterTypes = cos2.getParameterTypes();for(Class cla:parameterTypes){System.out.println("參數(shù)類型"+cla.toString());}}//根據(jù)構(gòu)造器創(chuàng)建一個(gè)對(duì)象//這個(gè)創(chuàng)建對(duì)象的方式有2個(gè)條件,第一是通過(guò)有參構(gòu)造器創(chuàng)建的,第二,構(gòu)造器對(duì)象必須通過(guò)傳入?yún)?shù)信息的getConstructor得到。//第一個(gè)條件,對(duì)于無(wú)參構(gòu)造方法就可以創(chuàng)建的對(duì)象,不需要得到構(gòu)造器對(duì)象,直接Class對(duì)象調(diào)用newInstance()方法就直接創(chuàng)建對(duì)象。//第二個(gè)條件,構(gòu)造器對(duì)象必須通過(guò)exampleObjectClass.getConstructor(String.class);這種形式得到。如果通過(guò)getConstructors得到構(gòu)造器數(shù)組//,然后調(diào)用指定的構(gòu)造器對(duì)象去創(chuàng)建對(duì)象在JDK1.8是會(huì)錯(cuò)的。但是JDK1.6是正常的Constructor constructor2 = exampleObjectClass.getConstructor(int.class,Integer.class);Object newInstance = constructor2.newInstance(1,100);System.out.println(newInstance.toString());4. 利用Java反射可以在運(yùn)行時(shí)得到一個(gè)類的變量信息
/*** 變量* 利用Java反射可以在運(yùn)行時(shí)得到一個(gè)類的變量信息,并且可以根據(jù)上面講的方式,創(chuàng)建一個(gè)對(duì)象,設(shè)置他的變量值。首先,通過(guò)如下方法,得到所有public的變量:*/Field[] fields = exampleObjectClass.getFields();for(Field fi:fields){System.out.println("變量為"+fi.toString());}//和構(gòu)造器一樣的得到方式一樣,我們可以指定一個(gè)參數(shù)名,然后得到指定的變量:Field field = exampleObjectClass.getField("age");System.out.println(field.toString());//更改變量的值Constructor constructor1 = exampleObjectClass.getConstructor(String.class);ExampleObject newInstance2 = (ExampleObject)constructor1.newInstance("heihei");System.out.println("原來(lái)的age"+newInstance2.getAge());field.set(newInstance2, 10);System.out.println("修改后age"+newInstance2.getAge());5. Java反射給我們除了給我們提供類的變量信息之外,當(dāng)然也給我們提供了方法的信息
/*** 方法* Java反射給我們除了給我們提供類的變量信息之外,當(dāng)然也給我們提供了方法的信息,* 反射可以讓我們得到方法名,方法的參數(shù),方法的返回類型,以及調(diào)用方法等功能。*/Method[] methods = exampleObjectClass.getMethods();for(Method me:methods){System.out.println("method="+me.getName());}//根據(jù)參數(shù)獲得具體方法Method method = exampleObjectClass.getMethod("setAge", int.class);System.out.println(method.getName());//獲取方法的參數(shù)類型Class<?>[] parameterTypes = method.getParameterTypes();for(Class clz:parameterTypes){System.out.println("參數(shù)名"+clz.getName());System.out.println("類型"+clz.getTypeParameters());}//獲得方法返回類型的Class<?> returnType = method.getReturnType();//此外,Java反射支持通過(guò)invoke調(diào)用得到的方法。例子如下://nvoke第一個(gè)參數(shù)是這個(gè)對(duì)象,第二個(gè)參數(shù)是變長(zhǎng)數(shù)組,傳入該方法的參數(shù)。和Field對(duì)象同樣,對(duì)于靜態(tài)方法同樣,可以傳入null,調(diào)用靜態(tài)方法。method.invoke(exampleObjectClass.newInstance(), 1);6. Java給我們提供了在運(yùn)行時(shí)獲取類的注解信息,可以得到類注解,方法注解,參數(shù)注解,變量注解
/*** 注解* Java給我們提供了在運(yùn)行時(shí)獲取類的注解信息,可以得到類注解,方法注解,參數(shù)注解,變量注解。* 與上面獲取方式一樣,Java提供了2種獲取方式,一種是獲取全部的注解,返回一個(gè)數(shù)組,第二種是指定得到指定的注解。* 我們以一個(gè)類注解為例,講解以下這兩種獲取方式。*///獲取類上的注解Class clz = AnnotationObject.class;Annotation[] annotations = clz.getAnnotations();Annotation annotation = clz.getAnnotation(AnnotationObject.class);//根據(jù)注解進(jìn)行后續(xù)處理for(Annotation ano:annotations){if(ano instanceof MyAnnotationFanshe){MyAnnotationFanshe annoFanshe=(MyAnnotationFanshe)ano;System.out.println(annoFanshe.name());System.out.println(annoFanshe.value());}}//獲取參數(shù)上的注解Method method2 = clz.getMethod("doOtherThing",String.class);Class[] params = method2.getParameterTypes();Annotation[][] annotationInParam = method2.getParameterAnnotations();int i = 0;for (Annotation[] annos: annotationInParam){Class para = params[i++];for (Annotation anno : annotations){if(annotation instanceof MyAnnotationFanshe){MyAnnotationFanshe myAnnotation = (MyAnnotationFanshe) annotation;System.out.println("param: " + para.getName());System.out.println("name : " + myAnnotation.name());System.out.println("value :" + myAnnotation.value());}}}7. 獲取泛型
/*** 泛型* 因?yàn)镴ava泛型是通過(guò)擦除來(lái)實(shí)現(xiàn)的,很難直接得到泛型具體的參數(shù)化類型的信息,* 但是我們可以通過(guò)一種間接的形式利用反射得到泛型信息。比如下面這個(gè)類:* 如果一個(gè)方法返回一個(gè)泛型類,我們可以通過(guò)method對(duì)象去調(diào)用getGenericReturnType來(lái)得到這個(gè)泛型類具體的參數(shù)化類型是什么。*/Class generObject = GenericObject.class;//反射得到返回類型為泛型類的方法Method method3 = generObject.getMethod("getLists");//調(diào)用getGenericReturnType得到方法返回類型中的參數(shù)化類型Type genericType = method3.getGenericReturnType();//判斷該type對(duì)象能不能向下轉(zhuǎn)型為ParameterizedTypeif(genericType instanceof ParameterizedType){//轉(zhuǎn)型成功,調(diào)用getActualTypeArguments得到參數(shù)化類型的數(shù)組,因?yàn)橛械姆盒皖?#xff0c;不只只有一個(gè)參數(shù)化類型如Map<K,V>ParameterizedType parameterizedType = ((ParameterizedType) genericType);//取出數(shù)組中的每一個(gè)的值,轉(zhuǎn)型為Class對(duì)象輸出Type[] types = parameterizedType.getActualTypeArguments();for (Type type : types){Class actualClz = ((Class) type);System.out.println("參數(shù)化類型為 : " + actualClz);}}//因?yàn)榉椒ǖ膮?shù)為泛型類型的可能不止一個(gè),所以通過(guò)getGenericParameterTypes得到是一個(gè)數(shù)組,//我們需要確定每一個(gè)元素,是否是具有參數(shù)化類型。后續(xù)的步驟與上面類似,就不多說(shuō)了。//如果連方法參數(shù)都不帶泛型類,那么只剩下最后一種情況,通過(guò)變量類型,即用Field類。例子如下:Field field1 = generObject.getField("lists");Type type = field1.getGenericType();if (type instanceof ParameterizedType){ParameterizedType parameterizedType = ((ParameterizedType) type);Type [] types = parameterizedType.getActualTypeArguments();for (Type type1 : types) {System.out.println("參數(shù)化類型 : " + ((Class) type1).getTypeName());}}8. Java反射可以對(duì)數(shù)組進(jìn)行操作
/*** 數(shù)組* Java反射可以對(duì)數(shù)組進(jìn)行操作,包括創(chuàng)建一個(gè)數(shù)組,訪問(wèn)數(shù)組中的值,以及得到一個(gè)數(shù)組的Class對(duì)象。* 下面,先說(shuō)簡(jiǎn)單的,創(chuàng)建數(shù)組以及訪問(wèn)數(shù)組中的值:在反射中使用Array這個(gè)類,是reflect包下面的。*///創(chuàng)建一個(gè)int類型的數(shù)組,長(zhǎng)度為3int[] intArray = (int[])Array.newInstance(int.class, 3);//通過(guò)反射形式給數(shù)組賦值for(int a=0;a<intArray.length;a++){Array.set(intArray, a, a+2);}//通過(guò)反射形式獲取數(shù)組中的值for(int b=0;b<intArray.length;b++){Array.get(intArray, b);}//上述就是創(chuàng)建數(shù)組,訪問(wèn)數(shù)組中的值利用反射方式//對(duì)于得到一個(gè)數(shù)組的Class對(duì)象,簡(jiǎn)單的可以用int[].class,或者利用Class.forName的形式得到,寫(xiě)法比較奇怪Class clz2 = Class.forName("[I");System.out.println(clz2.getTypeName());//這個(gè)forName中的字符串,[表示是數(shù)組,I表示是int,float就是F,double就是D等等,如果要得到一個(gè)普通對(duì)象的數(shù)組Class stringClz = Class.forName("[Ljava.lang.String;");//[表示是數(shù)組,L的右邊是類名,類型的右邊是一個(gè);;//這種方式獲取數(shù)組的Class對(duì)象實(shí)在是太繁瑣了。//在得到數(shù)組的Class對(duì)象之后,就可以調(diào)用他的一些獨(dú)特的方法,比如調(diào)用getComponentType來(lái)得到數(shù)組成員的類型信息,如int數(shù)組就//是成員類型就是int。System.out.println(clz2.getComponentType().getTypeName());總結(jié)
以上是生活随笔為你收集整理的java 反射调用方法_java的反射机制,以及通过反射获取方法,变量等操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: MySQL创建不了计划任务_MySQL创
- 下一篇: java解析xml中文字符乱码_Ecli