Java反射

Java反射

Reflection,程序在运行期可以拿到一个对象的所有信息

类信息

Class类作用

  • 每加载一个类,会先加载.class文件到内存,然后JVM会创建一个Class对象与之关联
  • 一个Class对象包含了.class的完整信息,包括类名、包名、父类、实现的接口、所有方法、字段等
  • 每个类在内存中只有一个 Class对象
  • .class是懒加载的

获取Class对象

Class只能由JVM创建

1
2
3
4
5
6
7
8
9
10
11
12
// 1.直接获取
Class cls1 = String.class;

// 2.通过实例获取
String str = "hello";
Class cls2 = str.getClass();

// 3.通过完整类名获取
Class cls3 = Class.forName("java.lang.String");

// Class实例在JVM中是唯一的
System.out.println(cls1 == cls2 && cls2 == cls3); // true

获取类信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static void main(String[] args) throws ClassNotFoundException {
printClassInfo(int.class);
printClassInfo(String.class);
printClassInfo(String[].class);
}

static void printClassInfo(Class cls) {
// 完整类名(包名 + 类名)
System.out.println("Class name: " + cls.getName());
// 类名
System.out.println("Simple name: " + cls.getSimpleName());
// 所在包名
if (cls.getPackage() != null) {
System.out.println("Package name: " + cls.getPackage().getName());
}
// 是否是接口
System.out.println("is interface: " + cls.isInterface());
// 是否是枚举类
System.out.println("is enum: " + cls.isEnum());
// 是否是数组
System.out.println("is array: " + cls.isArray());
// 是否是基本数据类型(boolean、byte、char、short、int、long、float、double)
System.out.println("is primitive: " + cls.isPrimitive());
}

获取父类

1
2
3
4
5
6
7
8
9
10
11
public class Main {
public static void main(String[] args) throws Exception {
Class i = Integer.class;
Class n = i.getSuperclass();
System.out.println(n); // class java.lang.Number

Class o = n.getSuperclass();
System.out.println(o); // class java.lang.Object
System.out.println(o.getSuperclass()); // null
}
}

获取实现的接口

不包含父类实现的接口

1
2
3
4
5
6
7
8
9
public class Main {
public static void main(String[] args) throws Exception {
Class s = Integer.class;
Class[] is = s.getInterfaces();
for (Class i : is) {
System.out.println(i);
}
}
}

实例信息

获取字段信息(Field)

  • Field getField(name):根据字段名获取某个public的field(包括父类)
  • Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
  • Field[] getFields():获取所有public的field(包括父类)
  • Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Main {
public static void main(String[] args) throws NoSuchFieldException {
Class stdClass = Student.class;
// 获取public字段"score"
System.out.println(stdClass.getField("score"));
// 获取继承的public字段"name"
System.out.println(stdClass.getField("name"));
// 获取private字段"grade"
System.out.println(stdClass.getDeclaredField("grade"));
}

class Student extends Person {
public int score;
private int grade;
}

class Person {
public String name;
}
}

Field字段包含了字段的所有信息

  • getName():返回字段名称
  • getType():返回字段类型
  • getModifiers():返回字段的修饰符,通过int表示

获取/设置字段值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Main {
public static void main(String[] args) throws Exception {
// 获取Class对象
Person p = new Person("Xiao Ming");
Class c = p.getClass();

// 获取Field对象
Field f = c.getDeclaredField("name");
f.setAccessible(true); // 如果字段是private,则需要设置为true

// 获取值
Object value = f.get(p);
System.out.println(value); // "Xiao Ming"

// 修改值
f.set(p, "Xiao Hong");
System.out.println(p.getName()); // "Xiao Hong"
}
}

class Person {
private String name;

public Person(String name) {
this.name = name;
}

public String getName() {
return this.name;
}
}

获取方法(Method)

  • Method getMethod(name, Class...):获取某个publicMethod(包括父类)
  • Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
  • Method[] getMethods():获取所有publicMethod(包括父类)
  • Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Main {
public static void main(String[] args) throws Exception {
Class stdClass = Student.class;
// 获取public方法getScore,参数为String:
System.out.println(stdClass.getMethod("getScore", String.class));
// 获取继承的public方法getName,无参数:
System.out.println(stdClass.getMethod("getName"));
// 获取private方法getGrade,参数为int:
System.out.println(stdClass.getDeclaredMethod("getGrade", int.class));
}
}

class Student extends Person {
public int getScore(String type) {
return 99;
}
private int getGrade(int year) {
return 1;
}
}

class Person {
public String getName() {
return "Person";
}
}

调用方法

调用普通的方法

1
2
3
4
5
6
7
8
9
10
11
12
public class Main {
public static void main(String[] args) throws Exception {
// String对象:
String s = "Hello world";
// 获取String substring(int)方法,参数为int:
Method m = String.class.getMethod("substring", int.class);
// 在s对象上调用该方法并获取结果:
String r = (String) m.invoke(s, 6);
// 打印调用结果:
System.out.println(r); // "world"
}
}

调用静态方法

invoke的第一个参数”实例”始终为null

1
2
3
4
5
6
7
8
9
10
public class Main {
public static void main(String[] args) throws Exception {
// 获取Integer.parseInt(String)方法,参数为String:
Method m = Integer.class.getMethod("parseInt", String.class);
// 调用该静态方法并获取结果:
Integer n = (Integer) m.invoke(null, "12345");
// 打印调用结果:
System.out.println(n);
}
}

调用私有方法

需要.setAccessible(true)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Main {
public static void main(String[] args) throws Exception {
Person p = new Person();
Method m = p.getClass().getDeclaredMethod("setName", String.class);
m.setAccessible(true);
m.invoke(p, "Bob");
System.out.println(p.name);
}
}

class Person {
String name;
private void setName(String name) {
this.name = name;
}
}

调用构造方法(Constructor)

只能调用无参构造

1
Person person = Person.class.newInstance();

通过Constructor调用有参构造

  • getConstructor(Class...):获取某个publicConstructor
  • getDeclaredConstructor(Class...):获取某个Constructor
  • getConstructors():获取所有publicConstructor
  • getDeclaredConstructors():获取所有Constructor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Main {
public static void main(String[] args) throws Exception {
// 获取构造方法Integer(int)
Constructor cons1 = Integer.class.getConstructor(int.class);
// 调用构造方法
Integer n1 = (Integer) cons1.newInstance(123);
System.out.println(n1);

// 获取构造方法Integer(String)
Constructor cons2 = Integer.class.getConstructor(String.class);
Integer n2 = (Integer) cons2.newInstance("456");
System.out.println(n2);
}
}

调用私有构造方法也需要setAccessible(true)


Java反射
http://xwww12.github.io/2025/10/05/java/java反射/
作者
xw
发布于
2025年10月5日
许可协议