Java反射知识点学习笔记


Java反射知识点学习笔记

原创 已于 2025-04-17 21:33:02 修改 · 粉丝可见 · 714 阅读 · 19 · 5 GEO检测 · 编辑
文章链接:https://blog.csdn.net/hacker_51/article/details/147292144

目录

[TOC]

Java反射是一种强大的编程机制,它允许程序在运行时检查和操作类、接口、字段和方法等元素。

一、定义

Java反射是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。这种动态获取信息以及动态调用对象方法的功能被称为Java语言的反射机制。( 反射允许对成员变量,成员方法和构造方法的信息进行编程访问

二、获取class对象的三种方式

1、Class.forName(“全类名”)

源代码阶段使用 Class.forName(“”) 方式获取反射对象。

2、类名.class

当类名加载到了内存中,使用 类名.class 方式获取class反射对象。

3、对象.getClass()

当内存中 new 了一个类对象,处于运行阶段。则使用 对象.getClass() 方式获取反射对象。

三、案例

1、获取 class 反射对象三种方式

假设我们有 Student 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.angindem.myreflect1;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}

代码案例:

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
package com.angindem.myreflect1;

public class MyReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
/**
* 获取class对象的三种方式:
* 1.Class.forName("全类名")
* 2.类名.class
* 3.对象.getClass()
*/
// 1.第一种方式
// 全类名: 包名 + 类名
// 最为常用的
Class sClass1 = Class.forName("com.angindem.myreflect1.Student");
System.out.println(sClass1);
// 2.第二种方式
// 一般更多的是当作参数进行传递
Class sClass2 = Student.class;
System.out.println(sClass2);
System.out.println(sClass1 == sClass2);
// 3.第三种方式
// 当我们已经有了这个类的对象时,才可以使用
Student s = new Student("angindem", 18);
Class sClass3 = s.getClass();
System.out.println(sClass3);
System.out.println(sClass1 == sClass3);
}
}

2、利用反射获取构造方法

假设我们有 Student 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.angindem.myreflect2;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
public class Student {
private String name;
private int age;
private Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
public Student(String name) {
this.name = name;
}
protected Student(int age) {
this.age = age;
}
}

代码案例:

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
package com.angindem.myreflect2;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class MyReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
/**
* Class 类中用于获取构造方法的方法
* Constructor<?>[] getConstructors()
* Constructor<?>[] getDeclaredConstructors()
* Constructor<?> getConstructor(Class<?>... parameterTypes)
* Constructor<?> getDeclaredConstructor(Class<?>... parameterTypes)
*
* Constructor类中用于创建对象的方法
* T newInstance(Object... initargs)
* setAccessible(boolean flag)
*/

// 1、获取 class 字节码文件对象
Class<?> clazz = Class.forName("com.angindem.myreflect2.Student");

// 2、获取所有公有构造器
// Constructor<?>[] cons = clazz.getConstructors();
// for (Constructor<?> con : cons){
// System.out.println(con);
// }

// 3、获取所有构造器(包括私有、受保护、默认、公有)
// Constructor<?>[] cons = clazz.getDeclaredConstructors();
// for (Constructor<?> con : cons){
// System.out.println(con);
// }

// 4、获取单个的构造器
Constructor<?> con1 = clazz.getDeclaredConstructor();
// System.out.println(con1);

Constructor<?> con2 = clazz.getDeclaredConstructor(String.class);
// System.out.println(con2);

Constructor<?> con3 = clazz.getDeclaredConstructor(int.class);
// System.out.println(con3);
//
Constructor<?> con4 = clazz.getDeclaredConstructor(String.class, int.class);
// System.out.println(con4);

// 获取权限修饰符
// int modifiers = con4.getModifiers();
// System.out.println(modifiers);

// 获取参数个数,获取参数的类型
// Parameter[] parameters = con4.getParameters();
// for (Parameter parameter : parameters) {
// System.out.println(parameter);
// }

// 通过反射构建对象,参数类型要符合构造函数的参数类型
// 小细节: getDeclaredConstructor 只能获取当前类中的构造器相关信息,当类中的构造器私有时,则无法进行调用
// 需要通过 setAccessible(true) 设置为 true,临时取消访问权限限制
con4.setAccessible(true); // 这种方式也称为:暴力反射
Student stu = (Student) con4.newInstance("angindem", 18);
System.out.println(stu);
}
}

扩展:关于 Modifier 的 常量字段值

修饰符 十六进制表示 描述
public 1 0x0001 表示该成员(类、方法、字段等)对所有类都可见。
private 2 0x0002 表示该成员只能在定义它的类内部访问。
protected 4 0x0004 表示该成员在定义它的类、同一包中的类以及所有子类中可见。
default 0 0x0000 表示该成员在定义它的类和同一包中的类中可见(没有显式修饰符)。
abstract 1024 0x0400 表示该类是抽象类,不能被实例化。
final 16 0x0010 表示该类不能被继承,或者该方法不能被重写,或者该字段是常量。
interface 512 0x0200 表示该类是一个接口。
static 8 0x0008 表示该字段或方法是静态的,属于类本身而不是类的实例。
transient 128 0x0080 表示该字段在序列化时不会被序列化。
volatile 64 0x0040 表示该字段的值可能会被多个线程同时访问,每次访问都需要从主内存中读取。
synchronized 32 0x0020 表示该方法是同步的,同一时间只能被一个线程访问。
native 256 0x0100 表示该方法是本地方法,其实现用非 Java 语言编写。

3、利用反射获取成员变量

假设我们有 Student 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.angindem.myreflect3;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Student {
private String name;
private int age;
public String gender;
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
}

代码案例:

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
package com.angindem.myreflect3;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class MyReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
/**
* Class 类中用于获取成员变量的方法
* Field[] getFields() 返回所有公有成员变量对象的数组
* Field[] getDeclaredFields() 返回所有成员变量对象的数组
* Field getField(String name) 返回一个公有成员变量对象
* Field getDeclaredField(String name) 返回一个成员变量对象
*
* Field 类中用于创建对象的方法
* void set(Object obj,Object value) 为成员变量赋值
* Object get(Object obj) 获取成员变量的值
*/

// 1、获取 class 字节码文件对象
Class<?> clazz = Class.forName("com.angindem.myreflect3.Student");

// 2、获取公有的成员变量
// Field[] fields = clazz.getFields();
// for (Field field : fields){
// System.out.println(field);
// }

// 3、获取所有成员变量(包括 私有的)
// Field[] fields = clazz.getDeclaredFields();
// for (Field field : fields){
// System.out.println(field);
// }

// 获取单个成员的变量
Field name = clazz.getDeclaredField("name");
System.out.println(name);

// 获取成员变量的权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);

// 获取成员变量的名称
String n = name.getName();
System.out.println(n);

// 获取成员变量的类型
Class<?> type = name.getType();
System.out.println(type);

// 获取成员变量的值
Student stu = new Student("angindem", 18, "男");
name.setAccessible(true); // 暴力反射:临时取消访问权限
Object value = name.get(stu);
System.out.println(value);

// 修改对象里面记录的值
name.set(stu, "ang");
System.out.println(stu);
}
}

4、利用反射获取成员方法

假设我们有 Student 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.angindem.myreflect4;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void sleep(){
System.out.println("sleep睡觉");
}
private void eat(String food){
System.out.println("在吃 " + food);
}
}

代码案例:

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
package com.angindem.myreflect4;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class MyReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
/**
* Class 类中用于获取成员方法的方法
* Method[] getMethods() 返回所有的公有成员方法对象的数组,包括父类中的
* Method[] getDeclaredMethods() 返回所有的成员方法对象的数组,不包括父类中的
* Method getMethod(String name,Class<?>... parameterTypes) 返回一个公有成员方法对象
* Method getDeclaredMethod(String name,Class<?>... parameterTypes) 返回一个成员方法对象
*
* Method类中用于创建对象的方法
* Object invoke(Object obj,Object... args) 运行方法
* 参数一:用 obj 对象调用该方法
* 参数二:调用方法的传递的参数(如果没有就不写)
* 返回值:方法的返回值(如果没有就不写)
* 获取方法的修饰符
* 获取方法的名字
* 获取方法的形参
* 获取方法的返回值
* 获取方法的抛出的异常
*/
// 1、获取 class 字节码文件对象
Class<?> clazz = Class.forName("com.angindem.myreflect4.Student");

// 2、获取里面所有的方法对象(包含父类中所有的公共方法)
// Method[] methods = clazz.getMethods();
// for (Method method : methods) {
// System.out.println(method);
// }

// 3、获取里面所有的方法对象(不能获取父类的,但是可以获取本类中私有的方法)
// Method[] methods = clazz.getDeclaredMethods();
// for (Method method : methods) {
// System.out.println(method);
// }
// 获取指定的单一方法
Method m = clazz.getDeclaredMethod("eat", String.class);
System.out.println(m);
// 获取方法的修饰符
int modifiers = m.getModifiers();
System.out.println(modifiers);
// 获取方法的名字
String name = m.getName();
System.out.println(name);
// 获取方法的形参
Class<?>[] parameterTypes = m.getParameterTypes();
for (Class<?> parameterType : parameterTypes){
System.out.println(parameterType);
}
// 获取方法的抛出异常
Class<?>[] exceptionTypes = m.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes){
System.out.println(exceptionType);
}
// 获取方法的返回值
Class<?> returnType = m.getReturnType();
System.out.println(returnType);
/** Method类中用于创建对象的方法
* Object invoke(Object obj,Object... args) 运行方法
* 参数一:用 obj 对象调用该方法
* 参数二:调用方法的传递的参数(如果没有就不写)
* 返回值:方法的返回值(如果没有就不写)
*/
Student s = new Student();
// 参数一s:表示方法的调用者
// 参数“汉堡包”:表示在调用方法的时候传递的实际参数
m.setAccessible(true);
String result = (String) m.invoke(s, "汉堡包");
System.out.println(result);
}
}

觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭

微信二维码

wechat pay

支付宝二维码

ali pay

Java反射知识点学习笔记
http://blog.angindem.cn/2025/04/17/Angindem-CSDN博客/181_181/
作者
Angindem
发布于
2025年4月17日
许可协议