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