java反射
Class类
通过Class实例获取class信息的方法称为反射(Reflection)
除了int的一些基本类型外 java的其他类型都是class(包括interface)。例如
- String
- Object
- Runnable
!!class(包括接口) 的本质是数据类型(type)
class 是jvm在执行过程中动态加载的 jvm在第一次读取到一种class类型时 将其加载进内存
每次加载一种class,jvm就为其创建一个Class类型的实例 并关联起来,这里的Class类型是一个名叫Class的class
1 | public final class Class { |
以String类为例,当JVM加载String类时,它首先读取String.class文件到内存,然后,为String类创建一个Class实例并关联起来:
1 | Class cls = new Class(String); |
这个Class实例是JVM内部创建的,如果我们查看JDK源码,可以发现Class类的构造方法是private,只有JVM能创建Class实例,我们自己的Java程序是无法创建Class实例的。
所以,JVM持有的每个Class实例都指向一个数据类型(class或interface):

一个Class实例包含了该class的所有完整信息:

因为jvm为每个实例都创建了对应的Class实例 在Class当中保存了实例的各种信息,所以如果获取了某个class实例,我们可以通过Class类来找到class的各种信息
??如何获取一个class的Class实例呢??
1.方法一:直接调用class的静态变量
1 | Class cls = String.class; |
2.方法二:如果我们有一个实例变量,可以通过该实例变量提供的getClass()方法获取
1 | String s = "Hello"; |
3.方法三:如果知道一个class的完整类名,可以通过静态方法Class.forName()获取
1 | Class cls = Class.forName("java.lang.String"); |
因为Class实例在JVM中是唯一的,所以,上述方法获取的Class实例是同一个实例。可以用==比较两个Class实例:
1 | Class cls1 = String.class; |
Class实例比较和instanceof的差别
1 | Integer n = new Integer(123); |
instanceof 不仅仅匹配指定类型 还匹配子类 而使用==判断class实例可以精确的判断数据类型 不会匹配子类
如果获取到一个Class 可以通过Class实例来创建对应类型的实例
1 | Class cls = String.class; |
Class的newInstance()可以创建类实例,但是它局限与只能调用public无参构造函数,带参数的或者private的就不行
动态加载
jvm在执行java程序的时候 不会一次性把所有用到的class全部加载到内存中 只会在第一次用到的时候加载
1 | //Main.java |
当执行main.java jvm知道了你要使用main.java 所以就会动态创建一个Main的Class对象 但是没有执行test方法是不会创建Person对象
访问字段
前面也说了当我们获取了任意一个object创建出它的class对象 那么我们就可以获得它的一切信息
如何通过class实例获取字段信息呢?
- Field getField(name):根据字段名获取某个public的field(包括父类)
- Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
- Field[] getFields():获取所有public的field(包括父类)
- Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
1 | //获取字段名 |
调用方法
Class类提供了以下几个方法来获取Method
- Method getMethod(name, Class…):获取某个public的Method(包括父类)
- Method getDeclaredMethod(name, Class…):获取当前类的某个Method(不包括父类)
- Method[] getMethods():获取所有public的Method(包括父类)
- Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
1 | //调用方法 |
一个Method对象包含了方法的所有信息
- getName():返回方法名称,例如:”getScore”;
- getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class;
- getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class};
- getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。
通过反射来调用substring方法
1 | String str = "hello world"; |
调用构造方法
我们通过new来创造类的实例 也可以通过反射的机制来创造类的实例
1 | Person p = new Person(); |
调用Class.newInstance()的局限就是它只能调用类的public 类型的无参构造函数 如果类的构造函数不是public 并且不是无参就无法调用
为了调用任意的构造方法,Java的反射API提供了Constructor对象,它包含一个构造方法的所有信息,可以创建一个实例。Constructor对象和Method非常类似,不同之处仅在于它是一个构造方法,并且,调用结果总是返回实例:
通过Class实例获取Constructor的方法如下:
- getConstructor(Class…):获取某个public的Constructor;
- getDeclaredConstructor(Class…):获取某个Constructor;
- getConstructors():获取所有public的Constructor;
- getDeclaredConstructors():获取所有Constructor。
注意Constructor总是当前类定义的构造方法,和父类无关,因此不存在多态的问题。
调用非public的Constructor时,必须首先通过setAccessible(true)设置允许访问。setAccessible(true)可能会失败。
获取父类 getSuperclass()
1 | //获取父类 |
获取接口 getInterfaces()
1 | //获取接口 |
getinterfaces不会返回它父类继承的接口
- Title: java反射
- Author: faith team
- Created at: 2023-08-01 11:21:05
- Updated at: 2025-11-29 09:01:08
- Link: https://redefine.ohevan.com/2023/08/01/20230801java反射/
- License: This work is licensed under CC BY-NC-SA 4.0.