2022.4.20 反射获取构造方法、成员变量、成员方法
获取构造方法
规则:
get表示获取
Declared表示私有
最后的s表示所有,复数形式
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 获得所有的构造(只能public修饰) |
Constructor<?>[] getDeclaredConstructors() | 获得所有的构造(包含private修饰) |
Constructor<T> getConstructor(Class<?>... parameterTypes) | 获取指定构造(只能public修饰) |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 获取指定构造(包含private修饰) |
在api帮助文档中搜索常量字段值:权限修饰符对应的常量值
代码示例:
Student
1 package com.xing.reflect; 2 3 import lombok.Data; 4 5 @Data 6 public class Student { 7 private String name; 8 private int age; 9 10 public Student() { 11 } 12 13 public Student(String name) { 14 this.name = name; 15 } 16 17 protected Student(int age) { 18 this.age = age; 19 } 20 21 private Student(String name, int age) { 22 this.name = name; 23 this.age = age; 24 } 25 26 }
GetConstructor
1 package com.xing.reflect; 2 3 4 import java.lang.reflect.Constructor; 5 import java.lang.reflect.InvocationTargetException; 6 import java.lang.reflect.Parameter; 7 8 public class GetConstructor { 9 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { 10 /* 11 Class类中用于获取构造方法的方法 12 Constructor<?>[] getConstructors() 返回所有公共构造方法对象的数组 13 Constructor<?>[] getDeclaredConstructors() 返回所有构造方法对象的数组 14 Constructor<T> getConstructor(Class<?>... parameterTypes) 返回单个公共构造方法对象 15 Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回单个构造方法对象 16 17 18 Constructor类中用于创建对象的方法 19 T newInstance(Object... initargs) 根据指定的构造方法创建对象 20 setAccessible(boolean flag) 设置为true,表示取消访问检查 21 */ 22 23 //1.获取class字节码文件对象 24 Class<?> clazz = Class.forName("com.xing.reflect.Student"); 25 26 //2.获取构造方法 27 Constructor<?>[] cons1 = clazz.getConstructors(); 28 for (Constructor<?> con : cons1) { 29 System.out.println(con); 30 /* public com.xing.reflect.Student(java.lang.String) 31 public com.xing.reflect.Student() */ 32 } 33 System.out.println("==================================="); 34 35 Constructor<?>[] cons2 = clazz.getDeclaredConstructors(); 36 for (Constructor<?> con : cons2) { 37 System.out.println(con); 38 /* private com.xing.reflect.Student(java.lang.String,int) 39 protected com.xing.reflect.Student(int) 40 public com.xing.reflect.Student(java.lang.String) 41 public com.xing.reflect.Student() */ 42 } 43 44 System.out.println("==================================="); 45 // 只获取空参 46 Constructor<?> con1 = clazz.getDeclaredConstructor(); 47 System.out.println(con1); 48 49 // 获取name的 根据其类型 50 Constructor<?> con2 = clazz.getDeclaredConstructor(String.class); 51 System.out.println(con2); 52 53 // 获取int的 根据其类型 54 Constructor<?> con3 = clazz.getDeclaredConstructor(int.class); 55 System.out.println(con3); 56 57 // 获取 name和int的 58 Constructor<?> con4 = clazz.getDeclaredConstructor(String.class,int.class); 59 System.out.println(con4); 60 System.out.println("==================================="); 61 62 // 获取权限修饰符 1-public 2-private 4-protected 63 int modifiers = con4.getModifiers(); 64 System.out.println(modifiers);//2 65 66 System.out.println("==================================="); 67 68 // 获取构造方法的所有参数 69 Parameter[] parameters = con4.getParameters(); 70 for (Parameter parameter : parameters) { 71 System.out.println(parameter); 72 /* java.lang.String name 73 int age */ 74 } 75 System.out.println("==================================="); 76 77 // 获取构造方法参数个数 78 int parameterCount = con4.getParameterCount(); 79 System.out.println(parameterCount);//2 80 System.out.println("==================================="); 81 82 // 获取参数类型 83 Class<?>[] parameterTypes = con4.getParameterTypes(); 84 for (Class<?> type : parameterTypes) { 85 System.out.println(type); 86 /* class java.lang.String 87 88 int */ 89 } 90 System.out.println("==================================="); 91 92 //暴力反射:表示临时取消权限校验 因为con4 是私有的构造方法 不能直接通过其构造方法创建对象 93 con4.setAccessible(true); 94 // 通过构造方法创建对象 传入此构造方法的参数 95 Student stu = (Student) con4.newInstance("张三", 23); 96 97 System.out.println(stu); 98 99 100 } 101 }
获取成员变量
规则:
get表示获取
Declared表示私有
最后的s表示所有,复数形式
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
方法名:
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有成员变量对象的数组:获取类中public类型的属性, 包括父类中的字段。 返回一个包含某些 Field 对象的数组,该数组包含此 Class 对象所表示的类或接口的所有可访问的成员变量 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到:获取类中所有的属性(public、protected、default、private),但不包括继承的属性, 返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有成员变量(包括私有) |
Field getField(String name) | 返回单个成员变量对象(只能拿public的):返回一个类或接口 及其父类的public成员变量 ,私有成员变量报错。 返回一个 Field 对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到:仅能获取类或接口本身的成员变量 , 返回一个 Field 对象,该对象返回此 Class 对象所表示的类或接口的指定已声明成员变量(包括私有)。 |
Field 类对象常用方法
-
获取变量的类型:
-
Field.getType():返回这个变量的类型
-
Field.getGenericType():如果当前属性有签名属性类型就返回,否则就返回 Field.getType()
-
isEnumConstant() : 判断这个属性是否是枚举类
-
-
获取成员变量的修饰符
-
Field.getModifiers() 以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符
-
-
获取和修改成员变量的值
-
getName() : 获取属性的名字
-
get(Object obj) 返回指定对象obj上此 Field 表示的字段的值
-
set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值
-
代码示例:
Person
1 package com.xing.reflect; 2 3 import lombok.Data; 4 5 @Data 6 public class Person { 7 private String name; 8 private int age; 9 public String gerder; 10 11 public Person() { 12 } 13 14 public Person(String name, int age, String gerder) { 15 this.name = name; 16 this.age = age; 17 this.gerder = gerder; 18 } 19 }
GetField
1 package com.xing.reflect; 2 3 import java.lang.reflect.Field; 4 5 public class GetField { 6 public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { 7 /* 8 Class类中用于获取成员变量的方法 9 Field[] getFields(): 返回所有公共成员变量对象的数组 10 Field[] getDeclaredFields(): 返回所有成员变量对象的数组 11 Field getField(String name): 返回单个公共成员变量对象 12 Field getDeclaredField(String name):返回单个成员变量对象 13 14 Field类中用于创建对象的方法 15 void set(Object obj, Object value):赋值 16 Object get(Object obj) 获取值 17 18 */ 19 20 //1.获取class字节码文件的对象 21 Class<?> clazz = Class.forName("com.xing.reflect.Person"); 22 23 //2.获取公共的成员变量 24 Field[] fields1 = clazz.getFields(); 25 for (Field field : fields1) { 26 System.out.println(field);//public java.lang.String com.xing.reflect.Person.gerder 27 } 28 System.out.println("========================="); 29 30 //3.获取所有的成员变量(包括私有的) 31 Field[] fields = clazz.getDeclaredFields(); 32 for (Field field : fields) { 33 System.out.println(field); 34 } 35 System.out.println("========================="); 36 37 //4. 获取单个公共的成员变量 38 Field gerder = clazz.getField("gerder"); 39 System.out.println(gerder); 40 System.out.println("========================="); 41 42 //5. 获取单个的成员变量(包括私有的) 43 Field name = clazz.getDeclaredField("name"); 44 System.out.println(name); 45 System.out.println("========================="); 46 47 //获取权限修饰符 1-public 2-private 4-protected 48 int modifiers = name.getModifiers(); 49 System.out.println(modifiers); 50 System.out.println("========================="); 51 52 //获取成员变量的名字 53 String n = name.getName(); 54 System.out.println(n); 55 System.out.println("========================="); 56 57 //获取成员变量的数据类型 58 Class<?> type = name.getType(); 59 System.out.println(type);//class java.lang.String 60 System.out.println("========================="); 61 62 63 //获取成员变量记录的值 64 Person s = new Person("zhangsan",23,"男"); 65 // 暴力反射:表示临时取消权限校验 因为name 是私有的成员变量 66 name.setAccessible(true); 67 // 获取s这个对象中name这个成员变量的具体值 68 String value = (String) name.get(s); 69 System.out.println(value);//zhangsan 70 System.out.println("========================="); 71 72 //修改对象里面记录的值 参数1:修改哪个对象的值 参数2: 将值修改为什么 73 name.set(s,"lisi"); 74 System.out.println(s);//Person(name=lisi, age=23, gerder=男) 75 76 } 77 }
获取成员方法
规则:
get表示获取
Declared表示私有
最后的s表示所有,复数形式
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有成员方法对象的数组(只能拿public的,包含父类中所有的公共方法) |
Method[] getDeclaredMethods() | 获取里面所有的方法对象(不能获取父类的方法,但是可以获取本类中私有的方法) |
Method getMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象(只能拿public的) |
Method getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
代码示例:
Cat
1 package com.xing.reflect; 2 3 import lombok.AllArgsConstructor; 4 import lombok.Data; 5 import lombok.NoArgsConstructor; 6 7 @Data 8 @NoArgsConstructor 9 @AllArgsConstructor 10 public class Cat { 11 private String name; 12 private int age; 13 14 public void sleep(){ 15 System.out.println("睡觉"); 16 } 17 18 private String eat(String something){ 19 System.out.println("在吃" + something); 20 return "奥利给"; 21 } 22 23 private void eat(String something,int a) { 24 System.out.println("在吃" + something); 25 } 26 } 27
GetMethod
1 package com.xing.reflect; 2 3 4 import java.lang.reflect.InvocationTargetException; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Parameter; 7 8 public class GetMethod { 9 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { 10 /* 11 Class类中用于获取成员方法的方法 12 Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的 13 Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的 14 Method getMethod(String name, Class<?>... parameterTypes) :返回单个公共成员方法对象 15 Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象 16 */ 17 18 //1. 获取class字节码文件对象 19 Class<?> clazz = Class.forName("com.xing.reflect.Cat"); 20 21 22 //2. 获取里面所有公共的方法对象(包含父类中所有的公共方法) 23 Method[] methods = clazz.getMethods(); 24 for (Method method : methods) { 25 System.out.println(method); 26 } 27 System.out.println("=================================="); 28 29 //3.获取里面所有的方法对象(不能获取父类的方法,但是可以获取本类中私有的方法) 30 Method[] methods2 = clazz.getDeclaredMethods(); 31 for (Method method : methods2) { 32 System.out.println(method); 33 } 34 System.out.println("=================================="); 35 36 //4. 获取指定的单一方法 参数1:方法的名字 参数2:方法形参 37 Method method = clazz.getDeclaredMethod("eat", String.class); 38 System.out.println(method); 39 System.out.println("=================================="); 40 41 // 获取方法的修饰符 42 int modifiers = method.getModifiers(); 43 System.out.println(modifiers); 44 System.out.println("=================================="); 45 46 // 获取方法的名字 47 String name = method.getName(); 48 System.out.println(name);//eat 49 System.out.println("=================================="); 50 51 // 获取方法的形参 52 Parameter[] parameters = method.getParameters(); 53 for (Parameter parameter : parameters) { 54 System.out.println(parameter); 55 } 56 System.out.println("=================================="); 57 58 //获取方法的抛出的异常 59 Class<?>[] exceptionTypes = method.getExceptionTypes(); 60 for (Class<?> exceptionType : exceptionTypes) { 61 System.out.println(exceptionType); 62 } 63 System.out.println("=================================="); 64 65 //方法运行 66 /*Method类中用于创建对象的方法 67 Object invoke(Object obj, Object... args):运行方法 68 参数一:用obj对象调用该方法 69 参数二:调用方法时传递的参数(如果没有就不写) 70 返回值:方法的返回值(如果没有就不写)*/ 71 72 73 Cat cat = new Cat(); 74 // 因为method返回的方法是私有的 75 method.setAccessible(true); 76 //参数一s:表示方法的调用者 77 //参数二"汉堡包":表示在调用方法的时候传递的实际参数 78 79 // cat这个对象调用method返回的eat方法,并给eat方法传递一个参数”汉堡包“ 80 String result = (String) method.invoke(cat, "汉堡包");//在吃汉堡包 81 System.out.println(result);// 打印的方法的返回值:奥利给 82 83 84 } 85 }
-
调用指定的方法 通过反射,调用类中的方法,通过Method类完成。
-
通过Class类的getMethod(String name,Class...parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
-
之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。
-
-
Object invoke(Object obj, Object ... args)
-
Object对应原方法的返回值,若原方法无返回值,此时返回null
-
若原方法若为静态方法,此时形参Object obj可为null
-
若原方法形参列表为空,则Object[] args为null
-
若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。
-
-
setAccessible
-
Method和Field、Constructor对象都有setAccessible()方法。
-
setAccessible作用是启动和禁用访问安全检查的开关。
-
参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
-
提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。
-
使得原本无法访问的私有成员也可以访问
-
-
参数值为false则指示反射的对象应该实施Java语言访问检查
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)