Java中,反射机制-Reflected
一、java的反射機制提供的功能:
- 在運行時判斷任意一個對象所屬的類
- 在運行時構造任意一個類的對象
- 在運行時判斷任意一個類所具有的成員變量和方法
- 運行時獲取泛型信息
- 在運行時調用任意一個對象的成員變量和方法
- 在運行時處理注解
- 生成動態代理
二、反射相關的主要API:
-
java.lang.Class : 代表一個類
1.程序經過javac.exe命令以后,會生成一個或多個字節碼文件(.calss后綴)。
接著我們使用就java.exe命令對字節碼文件進行解釋運行,此過程相當于將某個字節碼文件加載帶內存中。上述過程稱之為類的加載。
加載到內存中的類為運行時的類,運行時的類就作為Class的一個實例2.獲取Class的實例方式
方式1(掌握):Class<> c = 類名.class
方式2(掌握):類名 對象名 = new 類名()
Class c = 對象名.getClass()
方式3(掌握):Class c = Class.forName(String classPath)(注意:會拋異常)3.那些類型可以有Class對象
1.class :外部類、成員內部類、靜態內部類、局部內部類、匿名類
2.interface : 接口
3.[] : 數組
4.enum : 枚舉
5.annotation : 注解@interface
6.primitive type : 基本數據類型
7.void -
java.lang.reflect.Constructor : 代表類的構造器
1.獲取當前類的public構造器
Constructor[] 構造器對象名 = Class的實例名.getConstructors()2.獲取當前類的所有的構造器
Constructor[] 構造器對象名 = Class的實例名.getDecleardConstructors()3.獲取指定的構造器
Constructor 構造器對象名 = Class的實例名.getConstructor(參數1類型.class,…) -
創建運行時類的實例對象
方式1:使用的是類中的指定的構造器創建的類對象【不常用】
Constructor 構造器對象名 = Class的實例名.getConstructor(參數1類型.class,…) 獲取指定構造器對象
構造器對象名.setAccessible(true) 表示允許操作private成員
Object obj = 構造器對象名.newInstance(參數1,…) 通過指定構造器對象創建類的對象方式2:這樣直接使用的是類中的空參構造器創建的類對象【常用】
Object obj = Class的實例名.newInstance() -
java.lang.reflect.Field : 代表類的成員變量
1.獲取到類中public屬性(包含父類)【不建議使用
方法1:
Field[] f = Class的實例名.getFields()
方法2:
Field f = Class的實例名.getField(屬性名)2.獲取到類中自己的所有屬性(不含有父類):【建議使用】
方法1:
Field[] f = Class的實例名.getDeclaredFields()
方法2:
Field f = Class的實例名.getDeclaredField(屬性名)3.獲取到屬性的權限修飾符、數據類型、變量名。(了解)
int f.getModifiers() : 權限修飾符(0代表默認,1代表public,2代表private)Class f.getType().getName() : 數據類型
String f.getName() : 變量名
4.設置、獲取 屬性的值
非靜態的屬性:
前提操作:f.setAccessible(true) 表示允許操作private成員
設置:f.set(obj,value) obj表示給哪個對象的屬性設置,value為設置的值
獲取:f.get(obj) obj表示獲取哪個對象的屬性值,有返回值靜態的屬性:
前提操作:f.setAccessible(true) 表示允許操作private成員
設置:f.set(類.class,value) 類.class:表示當前類的靜態,value為設置的值
獲取:f.get(類.class) 類.class:表示當前類的靜態,有返回值 -
java.lang.reflect.Method : 代表類的方法
1.獲取到類中public方法(包含父類)【不推薦使用】
方法1:
Method[] m = Class的實例名.getMethods()方法2:
Method m = Class的實例名.getMethod(方法名,形參列表(默認為空))2.獲取到類中自己的所有方法(不含有父類)【推薦使用】
方法1:
Method[] m = Class的實例名.getDeclaredMethods()
方法2:
Method m = Class的實例名.getDeclaredMethod(方法名,形參列表(默認為空)) 例:String型的形參列表:String.class3.調用方法
非靜態方法:
前提操作:m.setAccessible(true) 表示允許操作private成員
調用:m.invoke(obj,實參1,…) obj表示給哪個對象的屬性設置,實參對應的方法的形參。invoke()返回值就是類中方法的返回值靜態方法:
前提操作:m.setAccessible(true) 表示允許操作private成員
調用:m.invoke(類.class,實參1,…) 類.class:表示當前類的靜態,實參對應的方法的形參。invoke()返回值就是類中方法的返回值 -
…
三、方法的補充:
1.獲取運行時類的父類
Class sp = Class的實例名.getSuperclass()
2.獲取運行時類的帶泛型的父類
Type sgp = Class的實例名.getGenericSuperclass()
3.獲取運行時類的帶泛型的父類的泛型(需要4步)
①Type sgp = Class的實例名.getGenericSuperclass(). : 獲取運行時類的帶泛型的父類
②ParameterizedType paramType = (parameterizedType)sgp : 強轉
③Type[] actTypeArg = paramType.getActualTypeArguments() : 獲取到實際的類型參數(也就是泛型)
④actTypeArg.getTypeName() : 獲取泛型名
4.獲取到當前運行時類的接口
Class[] interface = Class的實例名.getInterface()
如果想獲取到其父類的接口,那么得到父類然后在getInterface()
5.獲取當前運行時類所在的包
Package pk = Class的實例名.getPackage()
6.獲取當前運行時類聲明的注解
Annotation[] anno = Class的實例名.getAnnotations()
四、使用反射之前能對Person的操作:
- 創建Person類的實例化
- 通過對象當調用類中的非private類型的屬性、方法
五、使用反射之后能對Person的操作
- 創建Person類的實例化(調用構造器)
- 調用Person中的屬性
- 調用Person中的方法
- 調用Person中private的屬性、方法、構造器
上述過程的相關代碼舉例:
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;public class ReflectionTest {public static void main(String[] args) throws Exception {Person p1 = new Person("Joney",18);System.out.println(p1.age);System.out.println(p1.toString()+"\n");System.out.println("**************************");//1.通過反射創建Person的對象objClass c = Person.class;Object newInstance = c.newInstance();System.out.println(newInstance.toString());//通過getConstructor(參數1類型.class,...)獲取構造器對象Constructor constructor = c.getConstructor(String.class,int.class);//獲取構造器對象Object obj = constructor.newInstance("Mike",22);//通過構造器對象實例化Person//通過對象調用Person的方法System.out.println(obj.toString()+"\n"); //通過反射創建Person的對象obj調用方法//2.調屬性Field age = c.getDeclaredField("age"); //通過getDeclaredField("屬性")獲取到該屬性的對象age.set(obj, 20); //修改屬性值System.out.println(obj.toString()+"\n");//3.調方法Method print = c.getDeclaredMethod("print");//通過getDeclaredMethod()獲取到該方法的對象print.invoke(obj); //調用該print()System.out.println();//4.調用private結構//4.1通過getDeclaredConstructor((參數1類型.class,...)獲取私有構造器對象Constructor privateConstructor = c.getDeclaredConstructor(String.class);//獲取私有構造器對象privateConstructor.setAccessible(true);Object obj2 = privateConstructor.newInstance("Tom");//創建對象System.out.println(obj2.toString());//4.2通過getDeclaredField("屬性名")獲取到私有屬性的對象Field name = c.getDeclaredField("name");name.setAccessible(true);name.set(obj2, "Aimy");//修改屬性值System.out.println(obj2.toString());} } class Person{private String name;public int age;public Person(String name, int age) {super();this.name = name;this.age = age;}private Person(String name) {super();this.name = name;}public Person() {super();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public void print() {System.out.println("我是Person的print()");}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}}總結
以上是生活随笔為你收集整理的Java中,反射机制-Reflected的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql类似于excel的删除重复项_
- 下一篇: java美元兑换,(Java实现) 美元