目录
Java中的许多对象在运行时都有两种类型:
在程序运行时获取对象的真实信息有以下两种做法:
反射机制允许程序运行时借助Reflection API取得任何类的内部信息,并能直接操作对象的内部属性和方法
Reflection API提供了Constructor、Field和Method类,分别用于描述类的构造方法、属性和方法
Java反射机制的功能:
如:获取类对象的所有方法
- import java.lang.reflect.Method;
-
- public class Demo {
- public static void main(String[] args) throws ClassNotFoundException {
-
- Class cs = Class.forName("java.lang.String"); // 获取String类的Class对象
- Method[] methods = cs.getDeclaredMethods(); // 获取当前类对象的所有方法
- for (Method method: methods
- ) {
- System.out.println(method);
- }
- }
- }

Executable抽象类派生出了Constructor和Method两个子类,其提供了大量方法来获取参数、修饰符或注解等信息
| 方法 | 功能 |
| Parameter[ ] getParameters() | 获取所有形参,返回一个数组 |
| int getParameterCount() | 获取形参个数 |
| abstract int getModifiers() | 获取修饰符,返回的整数是修饰符public、protected、private、final、static、abstract等关键字所对应的常量 |
| boolean isVarArgs() | 判断是否包含数量可变的形参 |
Constructor类用于表示类的构造方法,通过调用Class对象的getConstructors()方法可以获取当前类的构造方法的集合
| 方法 | 功能 |
| String getName() | 返回构造方法的名称 |
| Class[ ] getParameterTypes() | 返回当前构造方法的参数类型 |
| int getModifiers() | 获取修饰符的整形标识,返回的整数是修饰符public、protected、private、final、static、abstract等关键字所对应的常量,需要使用Modifier工具类的方法解码后才能获得真实的修饰符 |
- package reflect;
-
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Modifier;
-
- public class ConstructorDemo {
- public static void main(String[] args) throws ClassNotFoundException {
-
- // 1.获取String类的对象
- Class cs = Class.forName("java.lang.String");
-
- // 2.返回所有构造方法
- Constructor[] constructors = cs.getConstructors();
-
- // 3.遍历所有构造方法
- for (Constructor constructor : constructors) {
-
- // 4.输出构造方法的名称
- String constructorName = constructor.getName();
- System.out.println(constructorName+"()");
-
- // 5.获取构造方法修饰符的整型标识
- int mod = constructor.getModifiers();
-
- // 6.使用Modifier工具类的方法输出真实的修饰符
- String modifier = Modifier.toString(mod);
- System.out.println(modifier);
-
- // 7.获取构造方法的参数类型
- Class[] paraTypes = constructor.getParameterTypes();
-
- // 8.输出构造方法的参数类型名称
- for (Class cas : paraTypes) {
- System.out.print(cas.getName() + " ");
- }
- System.out.println("\n------------------------");
- }
- }
- }

Method类用于封装方法的信息,调用Class对象的getMethods()方法或getMethod()可以获取当前类的所有方法或指定方法
| 方法 | 功能 |
| String getName() | 返回方法的名称 |
| Class[ ] getParameterTypes() | 返回当前方法的参数类型 |
| int getModifiers() | 返回修饰符的整形标识 |
| Class getReturnType() | 返回当前方法的返回类型 |
- package reflect;
-
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
-
- public class MethodDemo {
- public static void main(String[] args) throws ClassNotFoundException {
-
- // 1.获取String类的对象
- Class cs = Class.forName("java.lang.String");
-
- // 2.返回所有方法
- Method[] methods = cs.getMethods();
-
- // 3.遍历所有方法
- for (Method method : methods) {
-
- // 4.输出方法的名称
- String methodName = method.getName();
- System.out.println(methodName+"()");
-
- // 5.获取方法修饰符的整型标识
- int mod = method.getModifiers();
-
- // 6.使用Modifier工具类的方法输出真实的修饰符
- String modifier = Modifier.toString(mod);
- System.out.println(modifier);
-
- // 7.获取方法的参数类型
- Class[] paraTypes = method.getParameterTypes();
-
- // 8.输出方法的参数类型名称
- for (Class cas : paraTypes) {
- System.out.print(cas.getName() + " ");
- }
- System.out.println("\n------------------------");
- }
- }
- }

Field类用于封装属性的信息,调用Class对象的getFields()或getField()方法可以获取当前类的所有属性或指定属性
| 方法 | 功能 |
| String getName() | 返回属性的名称 |
| int getModifiers() | 返回修饰符的整型标识 |
| getXxx(Object obj) | 获取属性的值,此处Xxx对应Java8中的基本类型,如果属性是引用类型,直接使用get(Object obj)方法 |
| setXxx(Object obj,Xxx val) | 设置属性的值,此处Xxx对应Java8中的基本类型,如果属性是引用类型,直接使用set(Object obj,Object val)方法 |
| Class[ ] getType() | 返回当前属性的类型 |
- package reflect;
-
- import java.lang.reflect.Field;
- import java.lang.reflect.Modifier;
-
- class Student{
- private String name;
- protected int age;
- public String toString(){
- return ("姓名:" + name + "---" + "年龄:" + age);
- }
- }
- public class FieldDemo {
- public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
-
- // 1.获取Student类对应的Class对象
- Class studentClass = Student.class;
-
- // 2.返回所有属性(不包括超类属性)
- Field[] fields = studentClass.getDeclaredFields();
-
- // 3.遍历所有属性
- for (Field field : fields) {
-
- // 4.输出属性的类型
- Class fieldType = field.getType();
- System.out.println(fieldType);
-
- // 5.获取属性的修饰符
- int mod = field.getModifiers();
-
- // 6.使用Modifier工具类输出修饰符对应的常量
- String val = Modifier.toString(mod);
- System.out.println(val);
-
- // 7.输出属性的名称
- String fieldName = field.getName();
- System.out.println(fieldName);
- System.out.println("----------------");
- }
-
- // 1.创建一个Student对象
- Student student = new Student();
-
- // 2.获取Student类的属性对象
- // getDeclaredField:获取各种访问控制符的成员变量
- Field nameField = studentClass.getDeclaredField("name");
- Field ageField = studentClass.getDeclaredField("age");
-
- // 3.设置通过 反射 访问该类成员变量时取消访问权限检查
- nameField.setAccessible(true);
- ageField.setAccessible(true);
-
- // 4.获取Student类Class对象对应的实例
- Object obj = studentClass.newInstance();
-
- // 5.获取Student类的属性对象的值
- String name = (String) nameField.get(obj);
- int age = ageField.getInt(obj);
- System.out.println("Student类属性对象的值:" + name + ":" + age);
-
- // 6.设置Student类的属性对象的值
- nameField.set(student,"lisi");
- ageField.setInt(student,18);
-
- // 7.输出对象student的信息(默认调用toString()方法)
- System.out.println(student);
- }
- }

每个Parameter对象代表方法的一个参数,调用Class对象getParameters()可以获取当前方法的所有参数,Parameter类中提供许多方法获取参数信息
| 方法 | 功能 |
| int getModifiers() | 返回参数的修饰符的整型标识 |
| String getNmae() | 返回参数的形参名 |
| Type getParameterizedType() | 获取带泛型的形参类型 |
| Class<?> getType() | 获取形参类型 |
| boolean isVarArgs() | 判断该参数是否是可变参数 |
| boolean isNamePresent() | 判断.class文件中是否包含方法的形参名信息 |
- package reflect;
-
- import java.lang.reflect.Method;
- import java.lang.reflect.Parameter;
-
- class MethodParameter{
- public void test1(String str){
-
- }
- public void test2(int val, boolean bool){
-
- }
- }
- public class ParameterDemo {
- public static void main(String[] args) {
-
- // 1.获取MethodParameter类的Class对象
- Class cls = MethodParameter.class;
-
- // 2.获取MethodParameter类的所有方法
- Method[] methods = cls.getMethods();
-
- // 3.遍历MethodParameter类的所有方法
- for (Method method : methods) {
-
- // 4.输出该方法名
- String methodName = method.getName();
- System.out.println("方法名:" + methodName);
-
- // 5.输出该方法的形参个数
- int count = method.getParameterCount();
- System.out.println("形参个数:" + count);
-
- // 6.获取该方法的所有参数
- Parameter[] parameters = method.getParameters();
-
- // 7.遍历该方法的所有参数
- for (Parameter parameter : parameters) {
-
- // 8.输出参数名
- System.out.println("参数名:" + parameter.getName());
-
- // 9.输出形参类型
- System.out.println("形参类型:" + parameter.getType());
-
- // 10.输出泛型类型
- System.out.println("泛型类型:" + parameter.getParameterizedType());
- System.out.println("——————————————————————————————");
- }
- }
- }
- }

使用javac命令编译java源文件时,默认生成的.class文件不包含方法形参名信息,所以调用getName()不能得到正确的形参名
如果希望javac命令编译java源文件时保留形参信息,则需要为编译命令指定-parameters选项