JAVA反射-反射回顾

本文最后更新于:May 13, 2023 pm

积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里,不积小流无以成江海。齐骥一跃,不能十步,驽马十驾,功不在舍。面对悬崖峭壁,一百年也看不出一条裂缝来,但用斧凿,能进一寸进一寸,能进一尺进一尺,不断积累,飞跃必来,突破随之。

目录

前序

Class、class(类)、对象三者的关系。

类似于:

准备工作

这里定义两个类:一个父类、一个子类。

父类:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package com.tothefor.motorcode.Dro.StuClass;

import lombok.*;
import lombok.experimental.SuperBuilder;

/**
* @Author DragonOne
* @Date 2022/10/21 06:48
* @Title
* @Description
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@ToString
public class FatherClass {
private int age;
public String name;
protected Long money;
Integer sex;

// 默认
void defaultFatherVoid() {
System.out.println("FatherClass defaultFatherVoid");
}

static void defaultFatherStaticVoid() {
System.out.println("FatherClass defaultFatherStaticVoid");
}

int defaultFatherInt() {
System.out.println("FatherClass defaultFatherInt");
return 7;
}

static int defaultFatherStaticInt() {
System.out.println("FatherClass defaultFatherStaticInt");
return 7;
}

// 私有方法
private void privateFatherVoid() {
System.out.println("FatherClass privateFatherVoid");
}

private static void privateFatherStaticVoid() {
System.out.println("FatherClass privateFatherStaticVoid");
}

private int privateFatherInt() {
System.out.println("FatherClass privateFatherInt");
return 7;
}

private static int privateFatherStaticInt() {
System.out.println("FatherClass privateFatherStaticInt");
return 7;
}

// 受保护方法
protected void protectedFatherVoid() {
System.out.println("FatherClass protectedFatherVoid");
}

protected static void protectedFatherStaticVoid() {
System.out.println("FatherClass protectedFatherStaticVoid");
}

protected int protectedFatherInt() {
System.out.println("FatherClass protectedFatherInt");
return 7;
}

protected static int protectedFatherStaticInt() {
System.out.println("FatherClass protectedFatherStaticInt");
return 7;
}

//公开方法
public void publicFatherVoid() {
System.out.println("FatherClass publicFatherVoid");
}

public static void publicFatherStaticVoid() {
System.out.println("FatherClass publicFatherStaticVoid");
}

public int publicFatherInt() {
System.out.println("FatherClass publicFatherInt");
return 7;
}

public static int publicFatherStaticInt() {
System.out.println("FatherClass publicFatherStaticInt");
return 7;
}

}

子类:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package com.tothefor.motorcode.Dro.StuClass;

import lombok.*;
import lombok.experimental.SuperBuilder;

/**
* @Author DragonOne
* @Date 2022/10/21 06:49
* @Title
* @Description
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@ToString
public class SonClass extends FatherClass {
private int sonAge;
public String sonName;
protected Long sonMoney;
Integer sonSex;

public SonClass(int sonAge) {
this.sonAge = sonAge;
}
// 默认
void defaultSonVoid() {
System.out.println("SonClass defaultSonVoid");
}
static void defaultSonStaticVoid() {
System.out.println("SonClass defaultSonStaticVoid");
}
int defaultSonInt() {
System.out.println("SonClass defaultSonInt");
return 7;
}
static int defaultSonStaticInt() {
System.out.println("SonClass defaultSonStaticInt");
return 7;
}

// 私有方法
private void privateSonVoid() {
System.out.println("SonClass privateSonVoid");
}
private static void privateSonStaticVoid() {
System.out.println("SonClass privateSonStaticVoid");
}
private int privateSonInt() {
System.out.println("SonClass privateSonInt");
return 7;
}
private static int privateSonStaticInt() {
System.out.println("SonClass privateSonStaticInt");
return 7;
}

// 受保护方法
protected void protectedSonVoid() {
System.out.println("SonClass protectedSonVoid");
}
protected static void protectedSonStaticVoid() {
System.out.println("SonClass protectedSonStaticVoid");
}
protected int protectedSonInt() {
System.out.println("SonClass protectedSonInt");
return 7;
}
protected static int protectedSonStaticInt() {
System.out.println("SonClass protectedSonStaticInt");
return 7;
}

//公开方法
public void publicSonVoid() {
System.out.println("SonClass publicSonVoid");
}
public static void publicSonStaticVoid() {
System.out.println("SonClass publicSonStaticVoid");
}
public int publicSonInt() {
System.out.println("SonClass publicSonInt");
return 7;
}
public static int publicSonStaticInt() {
System.out.println("SonClass publicSonStaticInt");
return 7;
}
}

获取Class

有三种方式:通过 全限定名称、类、对象 进行获取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.tothefor.motorcode.Dro.StuClass;

/**
* @Author DragonOne
* @Date 2022/10/21 06:50
* @Title
* @Description
*/
public class TestClass {
public static void main(String[] args) throws Exception{
// 方式一
Class<?> clz1 = Class.forName("com.tothefor.motorcode.Dro.StuClass.FatherClass");
System.out.println(clz1);
// 方式二
Class<FatherClass> fatherClassClass = FatherClass.class;
System.out.println(fatherClassClass);
// 方式三
FatherClass fatherClass = new FatherClass();
Class<? extends FatherClass> aClass = fatherClass.getClass();
System.out.println(aClass);

}
}

输出:

1
2
3
class com.tothefor.motorcode.Dro.StuClass.FatherClass
class com.tothefor.motorcode.Dro.StuClass.FatherClass
class com.tothefor.motorcode.Dro.StuClass.FatherClass

特殊情况

基本数据类型也是可以获取对应的Class,如下:

1
2
3
4
Class<Integer> integerClass = int.class;
System.out.println(integerClass);
Class<Long> longClass = long.class;
System.out.println(longClass);

虽然显示的是对应的包装类,但实际上获取到的还是基本数据类型,输出结果:

1
2
int
long

还可以利用包装类型获取基本类型的Class,如下:

1
2
Class<Integer> type = Integer.TYPE;
System.out.println(type); //int

这里和上面的一样,虽然显示的是Integer,但实际上是基本类型。

⚠️注意:Integer.class 获取到的才是包装类型的Class。

TYPE源码如下:

1
public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("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
package com.tothefor.motorcode.Dro.StuClass;

import com.alibaba.fastjson.JSON;

import java.util.Arrays;

/**
* @Author DragonOne
* @Date 2022/10/21 06:50
* @Title
* @Description
*/
public class TestClass {
public static void main(String[] args) throws Exception {
Class<SonClass> sonClassClass = SonClass.class;
// 获取类的全限定名称
System.out.println(sonClassClass.getName());
// 获取类名
System.out.println(sonClassClass.getSimpleName());
// 获取父类的clas
Class<? super SonClass> superclass = sonClassClass.getSuperclass();
System.out.println(superclass);
// 获取实现的接口
Class<?>[] interfaces = sonClassClass.getInterfaces();
System.out.println(Arrays.toString(interfaces));
}
}


⚠️注意:因为Java中继承只能单继承,实现可以多实现。所有,一个是单个的结果,一个是数组。

输出:

1
2
3
4
com.tothefor.motorcode.Dro.StuClass.SonClass
SonClass
class com.tothefor.motorcode.Dro.StuClass.FatherClass
[]

获取构造方法

获取public所有

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.tothefor.motorcode.Dro.StuClass;

import com.alibaba.fastjson.JSON;

import java.lang.reflect.Constructor;
import java.util.Arrays;

/**
* @Author DragonOne
* @Date 2022/10/21 06:50
* @Title
* @Description
*/
public class TestClass {
public static void main(String[] args) throws Exception {
Class<SonClass> sonClassClass = SonClass.class;
Constructor<?>[] constructors = sonClassClass.getConstructors();
System.out.println(Arrays.toString(constructors));
}
}

输出:

1
[public com.tothefor.motorcode.Dro.StuClass.SonClass(int,java.lang.String,java.lang.Long,java.lang.Integer), public com.tothefor.motorcode.Dro.StuClass.SonClass(), public com.tothefor.motorcode.Dro.StuClass.SonClass(int)]

⚠️注意:该方法只能获取public修饰的构造方法!!!

获取public指定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.tothefor.motorcode.Dro.StuClass;

import com.alibaba.fastjson.JSON;

import java.lang.reflect.Constructor;
import java.util.Arrays;

/**
* @Author DragonOne
* @Date 2022/10/21 06:50
* @Title
* @Description
*/
public class TestClass {
public static void main(String[] args) throws Exception {
Class<SonClass> sonClassClass = SonClass.class;
// 获取public修饰的无参构造方法
Constructor<SonClass> constructor = sonClassClass.getConstructor();
System.out.println(constructor);
// 获取指定的public修饰的有参构造方法
Constructor<SonClass> constructor1 = sonClassClass.getConstructor(int.class);
System.out.println(constructor1);
}
}

输出:

1
2
public com.tothefor.motorcode.Dro.StuClass.SonClass()
public com.tothefor.motorcode.Dro.StuClass.SonClass(int)

⚠️注意:如果构造方法中为int类型,在获取指定构造方法传入的参数时,不能使用Integer.class。

获取所有修饰泛的构造方法

和获取public的构造方法使用一样,只不过调用的方法改为:getDeclaredConstructorsgetDeclaredConstructors。该方法的两种形式,和public的一模一样使用。

获取成员变量

和获取构造方法类似,分为public和所有。

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
package com.tothefor.motorcode.Dro.StuClass;

import com.alibaba.fastjson.JSON;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Arrays;

/**
* @Author DragonOne
* @Date 2022/10/21 06:50
* @Title
* @Description
*/
public class TestClass {
public static void main(String[] args) throws Exception {
Class<SonClass> sonClassClass = SonClass.class;
// 获取指定的public成员变量
System.out.println(sonClassClass.getField("sonName"));
// 获取任意指定的成员变量
System.out.println(sonClassClass.getDeclaredField("sonAge"));
// 获取public的成员变量,包括父类中的(特殊)
Field[] fields = sonClassClass.getFields();
System.out.println(Arrays.toString(fields));
// 获取所有的成员变量
Field[] declaredFields = sonClassClass.getDeclaredFields();
System.out.println(Arrays.toString(declaredFields));
}
}

输出:

1
2
3
4
public java.lang.String com.tothefor.motorcode.Dro.StuClass.SonClass.sonName
private int com.tothefor.motorcode.Dro.StuClass.SonClass.sonAge
[public java.lang.String com.tothefor.motorcode.Dro.StuClass.SonClass.sonName, public java.lang.String com.tothefor.motorcode.Dro.StuClass.FatherClass.name]
[private int com.tothefor.motorcode.Dro.StuClass.SonClass.sonAge, public java.lang.String com.tothefor.motorcode.Dro.StuClass.SonClass.sonName, protected java.lang.Long com.tothefor.motorcode.Dro.StuClass.SonClass.sonMoney, java.lang.Integer com.tothefor.motorcode.Dro.StuClass.SonClass.sonSex]

获取成员方法

方法名称和上面的类似,功能也是一样的。唯一不同的是获取指定方法时,不仅要传入方法名称,还要传入对应的参数class。

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
32
33
package com.tothefor.motorcode.Dro.StuClass;

import com.alibaba.fastjson.JSON;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
* @Author DragonOne
* @Date 2022/10/21 06:50
* @Title
* @Description
*/
public class TestClass {
public static void main(String[] args) throws Exception {
Class<SonClass> sonClassClass = SonClass.class;
// 获取所有public的方法,包括父类
Method[] methods = sonClassClass.getMethods();
System.out.println(Arrays.toString(methods));
// 获取public修饰的指定的无参方法,若有参则需要传入对应参数的class
Method defaultSonVoid = sonClassClass.getMethod("publicSonVoid");
System.out.println(defaultSonVoid);

// 获取所有的方法
Method[] declaredMethods = sonClassClass.getDeclaredMethods();
System.out.println(Arrays.toString(declaredMethods));
// 获取指定的无参方法,若有参则需要传入对应参数的class
Method privateSonVoid = sonClassClass.getDeclaredMethod("privateSonVoid");
System.out.println(privateSonVoid);
}
}

输出:

1
2
3
4
[public static com.tothefor.motorcode.Dro.StuClass.SonClass$SonClassBuilder com.tothefor.motorcode.Dro.StuClass.SonClass.builder(), public void com.tothefor.motorcode.Dro.StuClass.SonClass.publicSonVoid(), public static void com.tothefor.motorcode.Dro.StuClass.SonClass.publicSonStaticVoid(), public int com.tothefor.motorcode.Dro.StuClass.SonClass.publicSonInt(), public static int com.tothefor.motorcode.Dro.StuClass.SonClass.publicSonStaticInt(), public int com.tothefor.motorcode.Dro.StuClass.SonClass.getSonAge(), public java.lang.String com.tothefor.motorcode.Dro.StuClass.SonClass.getSonName(), public java.lang.Long com.tothefor.motorcode.Dro.StuClass.SonClass.getSonMoney(), public java.lang.Integer com.tothefor.motorcode.Dro.StuClass.SonClass.getSonSex(), public void com.tothefor.motorcode.Dro.StuClass.SonClass.setSonAge(int), public void com.tothefor.motorcode.Dro.StuClass.SonClass.setSonName(java.lang.String), public void com.tothefor.motorcode.Dro.StuClass.SonClass.setSonMoney(java.lang.Long), public void com.tothefor.motorcode.Dro.StuClass.SonClass.setSonSex(java.lang.Integer), public boolean com.tothefor.motorcode.Dro.StuClass.SonClass.equals(java.lang.Object), public java.lang.String com.tothefor.motorcode.Dro.StuClass.SonClass.toString(), public int com.tothefor.motorcode.Dro.StuClass.SonClass.hashCode(), public static com.tothefor.motorcode.Dro.StuClass.FatherClass$FatherClassBuilder com.tothefor.motorcode.Dro.StuClass.FatherClass.builder(), public void com.tothefor.motorcode.Dro.StuClass.FatherClass.setMoney(java.lang.Long), public java.lang.Integer com.tothefor.motorcode.Dro.StuClass.FatherClass.getSex(), public void com.tothefor.motorcode.Dro.StuClass.FatherClass.setSex(java.lang.Integer), public void com.tothefor.motorcode.Dro.StuClass.FatherClass.setAge(int), public java.lang.Long com.tothefor.motorcode.Dro.StuClass.FatherClass.getMoney(), public int com.tothefor.motorcode.Dro.StuClass.FatherClass.getAge(), public void com.tothefor.motorcode.Dro.StuClass.FatherClass.publicFatherVoid(), public static void com.tothefor.motorcode.Dro.StuClass.FatherClass.publicFatherStaticVoid(), public int com.tothefor.motorcode.Dro.StuClass.FatherClass.publicFatherInt(), public static int com.tothefor.motorcode.Dro.StuClass.FatherClass.publicFatherStaticInt(), public java.lang.String com.tothefor.motorcode.Dro.StuClass.FatherClass.getName(), public void com.tothefor.motorcode.Dro.StuClass.FatherClass.setName(java.lang.String), public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public final native java.lang.Class java.lang.Object.getClass(), public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll()]
public void com.tothefor.motorcode.Dro.StuClass.SonClass.publicSonVoid()
[public static com.tothefor.motorcode.Dro.StuClass.SonClass$SonClassBuilder com.tothefor.motorcode.Dro.StuClass.SonClass.builder(), protected boolean com.tothefor.motorcode.Dro.StuClass.SonClass.canEqual(java.lang.Object), void com.tothefor.motorcode.Dro.StuClass.SonClass.defaultSonVoid(), private void com.tothefor.motorcode.Dro.StuClass.SonClass.privateSonVoid(), public void com.tothefor.motorcode.Dro.StuClass.SonClass.publicSonVoid(), static void com.tothefor.motorcode.Dro.StuClass.SonClass.defaultSonStaticVoid(), int com.tothefor.motorcode.Dro.StuClass.SonClass.defaultSonInt(), static int com.tothefor.motorcode.Dro.StuClass.SonClass.defaultSonStaticInt(), private static void com.tothefor.motorcode.Dro.StuClass.SonClass.privateSonStaticVoid(), private int com.tothefor.motorcode.Dro.StuClass.SonClass.privateSonInt(), private static int com.tothefor.motorcode.Dro.StuClass.SonClass.privateSonStaticInt(), protected void com.tothefor.motorcode.Dro.StuClass.SonClass.protectedSonVoid(), protected static void com.tothefor.motorcode.Dro.StuClass.SonClass.protectedSonStaticVoid(), protected int com.tothefor.motorcode.Dro.StuClass.SonClass.protectedSonInt(), protected static int com.tothefor.motorcode.Dro.StuClass.SonClass.protectedSonStaticInt(), public static void com.tothefor.motorcode.Dro.StuClass.SonClass.publicSonStaticVoid(), public int com.tothefor.motorcode.Dro.StuClass.SonClass.publicSonInt(), public static int com.tothefor.motorcode.Dro.StuClass.SonClass.publicSonStaticInt(), public int com.tothefor.motorcode.Dro.StuClass.SonClass.getSonAge(), public java.lang.String com.tothefor.motorcode.Dro.StuClass.SonClass.getSonName(), public java.lang.Long com.tothefor.motorcode.Dro.StuClass.SonClass.getSonMoney(), public java.lang.Integer com.tothefor.motorcode.Dro.StuClass.SonClass.getSonSex(), public void com.tothefor.motorcode.Dro.StuClass.SonClass.setSonAge(int), public void com.tothefor.motorcode.Dro.StuClass.SonClass.setSonName(java.lang.String), public void com.tothefor.motorcode.Dro.StuClass.SonClass.setSonMoney(java.lang.Long), public void com.tothefor.motorcode.Dro.StuClass.SonClass.setSonSex(java.lang.Integer), public boolean com.tothefor.motorcode.Dro.StuClass.SonClass.equals(java.lang.Object), public java.lang.String com.tothefor.motorcode.Dro.StuClass.SonClass.toString(), public int com.tothefor.motorcode.Dro.StuClass.SonClass.hashCode()]
private void com.tothefor.motorcode.Dro.StuClass.SonClass.privateSonVoid()

提示:因为每个类中都有其他继承自Object的方法,所以这里的方法比较多。而且查询public修饰的方法时,不仅会把父类的查出来,还会把父类的父类也查询出来。

创建对象

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
package com.tothefor.motorcode.Dro;

import lombok.Data;

/**
* @Author DragonOne
* @Date 2022/10/20 06:24
* @Title
* @Description
*/
@Data
public class Box<T> {
private T first;
private String name;
private int age;

private Box(int age, String name) {
this.name = name;
this.age = age;
}

public Box() {
}
}

使用:

1
2
3
4
5
6
7
public static void main(String[] args) throws Exception {
Class<Box> boxClass = Box.class;
Constructor<Box> declaredConstructor = boxClass.getDeclaredConstructor(int.class, String.class);
declaredConstructor.setAccessible(true); // 如果是public的,则无需这句代码
Box box = declaredConstructor.newInstance(1, "23");
System.out.println(JSON.toJSONString(box));
}

⚠️注意:setAccessible(true)表示打破封装的限制,即可以执行私有方法。如果构造方法为public的,则无需进行此操作。并且必须放在使用的前面。

操作成员变量

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) throws Exception {
Class<Box> boxClass = Box.class;
// 通过无参构造创建对象
Box box = boxClass.getConstructor().newInstance();
// 获取指定属性
Field name = boxClass.getDeclaredField("name");
// 打破封装限制,使其可以进行操作
name.setAccessible(true);
// 赋值操作
name.set(box,"ttf");
System.out.println(JSON.toJSONString(box));
}

操作成员方法

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) throws Exception {
Class<Box> boxClass = Box.class;
Box box = boxClass.getConstructor().newInstance();
// 获取方法
Method setAge = boxClass.getMethod("setAge", int.class);
Method getAge = boxClass.getMethod("getAge");
// 执行方法
setAge.invoke(box, 13);
Object invoke = getAge.invoke(box);
System.out.println(invoke); // 13

}

获取方法参数

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) throws Exception {
Class<Box> boxClass = Box.class;
Box box = boxClass.getConstructor().newInstance();
// 获取方法
Method setAge = boxClass.getMethod("setAge", int.class);
// 获取方法所有的参数类型
Class<?>[] parameterTypes = setAge.getParameterTypes();
System.out.println(Arrays.toString(parameterTypes));

}

小总结

  • 档获取为public修饰符的时候,除了能获取本类之外,其父类的也可以进行获取。
  • 当获取所有修饰符的时候,只能获取本类的。