Java反射

学习文章:https://juejin.cn/post/6844904025607897096

Java反射的理解

Java的反射机制就是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能调用它的任意一个方法,无需在编译期确定具体的类和方法,而是在运行的时候通过字符串动态决定。

反射机制就是一种动态获取信息以及动态调用对象方法的功能。

正射

与反射相对应的就是正射,其实这也不是什么java的官方术语,只是相对于反射口头叫出来的说法。

正射就是Java最普通最直接的调用方式:在写代码时就明确指定类、方法和对象,通过new创建实例、用点.调用方法,所有类型和调用关系在编译期就已经确定,由编译器负责检查是否正确,而不是等到运行期再去动态查找。

在编写代码时,当需要使用到某一个类的时候,都会先了解这个类是做什么的。然后实例化这个类,接着用实例化好的对象进行操作,这就是正射。

1
2
Student student = new Student();//声明一个Student类型的对象
student.doHomework("数学");

Student student = new Student();

  • 第一个Student是类型名,定义的变量将来指向的是Student类型的对象
  • student是变量名,就是一个标识符用来在代码里表示这个对象
  • 第二个Student()是构造方法调用,用来创建一个真正的Student对象

先实例化一个student对象,然后调用doHomework方法,这段代码在还没有运行的时候就已经知道其中要运行的类是student和调用的方法是doHomework

反射

反射就是,一开始并不知道我们要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了

1
2
3
4
5
Class clazz = Class.forName("reflection.Student");
Method method = clazz.getMethod("doHomework", String.class);
Constructor constructor = clazz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, "语文");

这里就是获取了一个Student的原型,然后通过这个原型得到这个类的所有元信息(所有属性和方法)

这段代码是整个程序运行的时候,从字符串reflection.Student中才知道要操作的是类是Student

反射的作用

  • 让Java具有动态性:Java作为强类型语言,在代码编译时,对于已编译好的代码就不能改变了,而不像PHP中的eval(“任意代码”);的动态执行(就是传入什么就执行什么),但可以通过反射进行改变,比如修改已有对象的属性
  • 动态生成对象
  • 动态调用方法
  • 操作内部类和私有类

Class对象

**RTTI**运行时类型识别就是在程序运行过程中,识别一个对象的类型和类的信息

Java在运行时识别对象和类的信息的方式有两种:第一种就是传统的RTTI,它假定我们在编译期已知了所有类型;另一种就是反射机制,它允许我们在运行时才发现和使用类的信息。

每个类都有一个Class对象,当编译一个新类就会产生一个Class对象(也就是被保存在一个同名的.class文件中)

其实更直观的就是在IDEA中创建一个Java类文件,命名为Test

image-20260708165448489

文件开头用 class定义一个 Test 类型,在其中写代码,当JVM加载这个类时,会在内存中创建一个同名的Class对象,这个Class对象就保存了Test类相关的类型信息

image-20260708165446452

Class类的对象作用时运行时提供或获得某个对象的类型信息

反射的基本使用

获取Class类对象

创建reflection包,在包中创建TestReflection

方法一:使用Class.forName静态方法

1
Class class1 = Class.forName("reflection.Person");

forName方法存在于Class类中,会返回传入值的原型类

方法二:使用类的.class方法

1
Class class2 = Person.class;

方法三:使用实例对象的getClass()方法

1
2
Person testReflection = new Person();
Class class3 = testReflection.getClass();

利用getName输出,只返回纯粹的类名

image-20260708165443800

反射就是操作获得的class对象

从原型class类中实例化对象

方法一:使用newInstance,无参构造

1
Person  a = (Person) class3.newInstance();

方法二:使用getConstructor,有参构造

1
2
Constructor b = class3.getConstructor(String.class,int.class);
Person ab = (Person) b.newInstance("zhang", 18);

image-20260708165441340

这里就可以更进一步理解反射,先拥有原型class3,再调用其中的方法比如getConstructor

获取类中的属性

方法一:使用getFields()方法,只能获取public属性

1
2
3
4
Field[] personfileds= class3.getFields();
for(Field f:personfileds){
System.out.println(f);
}

image-20260708165439381

方法二:使用getDeclaredFields()方法,可以获取所有属性

1
2
3
4
Field[] personfileds= class3.getDeclaredFields();
for(Field f:personfileds){
System.out.println(f);
}

image-20260708165437387

方法三:通过变量名修改属性值

修改public属性值

1
2
3
Field namefield = class3.getField("name");
namefield.set(ab, "yin");
System.out.println(ab);

将原来name变量的值改成“yin”,这里要注意用到的还是getField方法,name应为public属性

image-20260708165435308

修改private属性值

1
2
3
4
Field namefield = class3.getDeclaredField("name");
namefield.setAccessible(true);
namefield.set(ab, "yin");
System.out.println(ab);

image-20260708165432953

调用类中的方法

方法一:通过getMethods方法获取

1
2
3
4
Method[] personmethod = class3.getMethods();
for(Method m:personmethod) {
System.out.println(m);
}

image-20260708165429044

方法二:通过方法名获取

调用public方法

1
2
Method y = class3.getMethod("action",String.class);
y.invoke(ab,"asdf");

image-20260708165426864

调用private方法

1
2
3
Method y = class3.getDeclaredMethod("action",String.class);
y.setAccessible(true);
y.invoke(ab,"asdf");

image-20260708165424115


Java反射
https://colourful228.github.io/2026/07/08/Java反射/
作者
Colourful
发布于
2026年7月8日
更新于
2026年7月8日
许可协议