哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:掘金/C站/腾讯云/阿里云/华为云/51CTO(全网同号);欢迎大家常来逛逛,互相学习。
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
上一期我们提到过反射(Reflection),给大家讲解的是它的一个重要特性:动态代理。学过 Java 的小伙伴都知道,反射是Java中的一项强大的功能,它允许程序在运行时动态地获取类的信息、访问类的构造方法、字段、方法等。Java 的反射机制使得我们能够在运行时检查和操作类的属性和行为,通常用于框架、库、工具等需要动态处理对象的场景,对吧(温习一遍)。
而在这篇文章中,我们将深入探讨 如何在Java 中运用反射机制进行"字段访问"?带着大家学习如何使用反射功能来访问和操作类的字段,包括私有字段、公共字段,以及如何通过反射对字段值进行修改,听起来是不是非常的cool!没错,我只教流批的玩意!
1. Java 反射机制概述
在 Java 中,反射是通过 java.lang.reflect
包来提供类和方法来实现的。反射机制能够让我们获取类的信息(如类名、父类、接口等),并能动态地操作类的实例。
常见的反射相关类有:
Class
:用于获取类的信息。Field
:用于访问类的字段(成员变量)。Method
:用于访问类的方法。Constructor
:用于访问类的构造方法。
通过反射,我们可以绕过访问修饰符(如 private
、protected
等)来访问类的成员,甚至动态地创建和操作类的实例。那废话不多讲,我们直接实操,手把手教学!
2. 获取类的字段
2.1 如何获取字段对象?
反射中,字段被表示为 Field
类的实例。要获取类的字段,首先需要通过 Class
对象来获取相应的字段信息,如何理解呢?接下来我给大家简单写个案例,演示一波你们就明白了。
首先随意定义一个带属性的对象,比如它有name属性、age属性等。示例代码如下:
java
/**
* @Author 喵手
* @date: 2025-04-15
*/
public class Person {
private String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
接着,我们通过反射获取该对象的属性值,看看究竟要如何获取?示例代码如下:
java
import java.lang.reflect.Field;
/**
* @Author 喵手
* @date: 2025-04-15
*/
public class ReflectionExample {
public static void main(String[] args) throws NoSuchFieldException {
Class<?> personClass = Person.class;
// 获取 public 字段 age
Field ageField = personClass.getField("age");
System.out.println("Field: " + ageField.getName()); // 输出:age
// 获取 private 字段 name
Field nameField = personClass.getDeclaredField("name");
System.out.println("Field: " + nameField.getName()); // 输出:name
}
}
运行效果展示如下:

可以看到,属性被正常获取。
2.2 如何获取类中的所有字段?
这里可以使用 getDeclaredFields()
方法可以获取类中所有的字段,包括私有字段、保护字段和公共字段。
java
import java.lang.reflect.Field;
/**
* @Author 喵手
* @date: 2025-04-15
*/
public class ReflectionExample1 {
public static void main(String[] args) {
Class<?> personClass = Person.class;
// 获取所有字段(包括私有字段)
Field[] fields = personClass.getDeclaredFields();
for (Field field : fields) {
System.out.println("Field: " + field.getName());
}
}
}
预期输出:
json
Field: name
Field: age
运行效果展示如下:

2.3 如何访问私有字段?
要访问类中的私有字段,需要先通过 setAccessible(true)
来取消 Java 的访问控制检查。这是因为默认情况下,Java 会保护私有字段不被外部访问。通过调用 setAccessible(true)
,我们可以突破 Java 的访问权限限制,允许反射访问私有字段。
java
import java.lang.reflect.Field;
/**
* @Author 喵手
* @date: 2025-04-15
*/
public class ReflectionExample2 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person("喵手", 25);
Class<?> personClass = person.getClass();
// 获取 private 字段 name
Field nameField = personClass.getDeclaredField("name");
// 取消 Java 的访问权限检查
nameField.setAccessible(true);
// 获取字段的值
String name = (String) nameField.get(person);
System.out.println("Name: " + name); // 输出:喵手
// 修改字段的值
nameField.set(person, "喵手大佬");
System.out.println("Modified Name: " + person.getName()); // 输出:喵手大佬
}
}
预期输出:
json
Name: 喵手
Modified Name: 喵手大佬
实际运行结果展示如下:

代码解析:
如上案例代码演示了如何通过 Java 反射机制访问和修改一个类的私有字段。如下是实现思路步骤:
-
创建对象 :首先,创建了一个
Person
类的对象person
,并初始化其name
和age
字段。 -
获取 Class 对象 :通过
person.getClass()
获取到Person
类的Class
对象,之后可以用反射操作该类的成员。 -
获取私有字段 :通过
personClass.getDeclaredField("name")
获取Person
类中的私有字段name
。这时name
字段虽然是private
,但反射允许我们访问。 -
取消访问权限检查 :使用
nameField.setAccessible(true)
取消 Java 默认的访问权限限制,允许访问私有字段。 -
读取字段值 :通过
nameField.get(person)
获取person
对象中name
字段的值,并输出。 -
修改字段值 :通过
nameField.set(person, "喵手大佬")
修改person
对象中name
字段的值,修改后的值可以通过调用person.getName()
查看。
2.4 如何访问静态字段?
静态字段属于类而不是实例,因此访问静态字段时,反射的使用方法稍有不同。我们可以通过 getField()
或 getDeclaredField()
来获取静态字段,并使用 Field
对象的 get()
方法来获取字段的值。
java
import java.lang.reflect.Field;
/**
* @Author 喵手
* @date: 2025-04-15
*/
public class ReflectionExample3 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Class<?> peopleClass = People.class;
// 获取静态字段 species
Field speciesField = peopleClass.getField("species");
// 获取静态字段的值
String speciesValue = (String) speciesField.get(null); // 静态字段不依赖于对象
System.out.println("Species: " + speciesValue); // 输出:哈咯,我是喵手!
// 修改静态字段的值
speciesField.set(null, "哈咯,我是帅哥!");
System.out.println("Modified Species: " + speciesField.get(null)); // 输出:哈咯,我是帅哥
}
}
预期输出:
json
Species: 哈咯,我是喵手!
Modified Species: 哈咯,我是帅哥!
实际运行结果展示如下:

代码解析:
如上案例代码演示了如何通过 Java 反射访问和修改类的静态字段。如下是实现思路步骤:
-
获取
Class
对象 :通过People.class
获取到People
类的Class
对象,可以用来操作该类的成员。 -
获取静态字段 :通过
peopleClass.getField("species")
获取People
类中的公有静态字段species
。注意,这里使用的是getField()
,它只能获取public
修饰的字段。如果字段是private
或其他访问修饰符,需要使用getDeclaredField()
。 -
获取静态字段的值 :通过
speciesField.get(null)
获取静态字段species
的值。对于静态字段,get()
方法的参数可以传入null
,因为静态字段不依赖于具体的实例对象。 -
修改静态字段的值 :通过
speciesField.set(null, "哈咯,我是帅哥!")
修改静态字段species
的值。同样,传入null
作为第一个参数,因为字段是静态的,不依赖于具体对象。 -
输出修改后的值 :再次通过
speciesField.get(null)
获取修改后的静态字段值,并输出。
这段代码的关键点是:静态字段是属于类的,而不是某个特定实例,因此使用反射时在操作静态字段时不需要指定对象实例,直接传入 null
即可。
2.5 如何修改字段的值?
通过反射,我们不仅可以访问字段,还可以修改字段的值。修改字段时需要注意以下几点:
- 如果字段是
private
,必须使用setAccessible(true)
来绕过访问控制。 - 必须确保所修改的字段类型与字段原本类型兼容。
例如,修改实例对象的字段值:
java
import java.lang.reflect.Field;
/**
* @Author 喵手
* @date: 2025-04-15
*/
public class ReflectionExample4 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Person person = new Person("喵手", 25);
Class<?> personClass = person.getClass();
// 获取 private 字段 name
Field nameField = personClass.getDeclaredField("name");
nameField.setAccessible(true); // 取消访问控制
// 修改字段的值
nameField.set(person, "帅哥");
System.out.println("Updated Name: " + person.getName()); // 输出:帅哥
}
}
预期输出:
json
Updated Name: 帅哥
实际运行结果展示如下:

代码解析:
如上案例代码演示了如何使用 Java 反射修改类的私有字段值。如下是实现思路步骤:
-
创建对象 :首先,创建了一个
Person
类的实例person
,并初始化name
为"喵手"
,age
为25
。 -
获取
Class
对象 :通过person.getClass()
获取Person
类的Class
对象,这个对象代表了Person
类的元数据,接下来通过它来操作该类的成员。 -
获取私有字段 :通过
personClass.getDeclaredField("name")
获取Person
类中的私有字段name
。由于该字段是私有的,反射默认是无法访问的。 -
取消访问控制 :通过
nameField.setAccessible(true)
来取消 Java 的访问控制限制,使得即使name
字段是私有的,也可以在反射中进行操作。 -
修改字段值 :通过
nameField.set(person, "帅哥")
修改person
对象中的name
字段的值。这里的person
是目标对象,"帅哥"
是新值。 -
输出修改后的值 :通过
person.getName()
输出修改后的name
字段的值,确认修改成功。
3. Class类相关方法解析
3.1 getFields()
getFields()
是 java.lang.Class
类的一个方法,用于获取当前类及其父类中所有 公共字段 (public
修饰符的字段)。与 getDeclaredFields()
不同,getFields()
只会返回类的 public
字段,并且会包括父类中继承的字段。
方法签名
java
public Field[] getFields() throws SecurityException
返回值
- 返回一个
Field[]
数组,其中包含了当前类及其所有父类声明的public
字段。
主要特点
- 仅包含公共字段 :
getFields()
只返回当前类及其父类中public
修饰符声明的字段,不包括private
、protected
或默认访问权限的字段。 - 包含父类字段 :
getFields()
会返回当前类和父类中继承下来的public
字段。如果父类有public
字段,子类也可以通过getFields()
获取。 - 访问控制 :与
getDeclaredFields()
不同,getFields()
返回的字段会根据其可见性进行过滤,只有public
字段才能被获取。
3.2 getDeclaredFields()
getDeclaredFields()
是 Class
类的一个方法,用于获取某个类(包括父类)中所有声明的字段(包括私有字段、保护字段和公共字段)。
方法签名
java
public Field[] getDeclaredFields() throws SecurityException
返回值
- 返回一个
Field[]
数组,其中包含了该类声明的所有字段(不包括继承自父类的字段)。 - 每个
Field
对象表示类中一个声明的字段。
主要特点
-
包括所有字段 :
getDeclaredFields()
会返回当前类中所有的字段,包括:- 私有字段 (
private
) - 保护字段 (
protected
) - 公共字段 (
public
) - 默认访问权限字段 (没有
public
、protected
、private
修饰符的字段)
- 私有字段 (
-
不包含父类字段 :如果当前类继承了父类,
getDeclaredFields()
只返回当前类声明的字段 ,不会包括父类的字段。要获取所有字段(包括父类的字段),可以使用getFields()
。 -
不检查访问权限 :通过
getDeclaredFields()
获取的字段对象,不会检查字段的访问修饰符。如果字段是private
或者是protected
,你依然可以通过Field
对象进行访问,只不过可能需要通过setAccessible(true)
来绕过 Java 的访问控制检查。
设置字段可访问
如果你想访问 private
或 protected
字段,需要调用 setAccessible(true)
方法来绕过 Java 的访问控制检查。
与 getFields()
的区别
getDeclaredFields()
:返回所有由类声明的字段,不考虑访问权限,不包括继承自父类的字段。getFields()
:只返回当前类及其父类中public
修饰的字段,无法获取private
或protected
字段。
4. 总结
Java 反射,提供了一种动态访问和操作类字段的方式,能够突破 Java 的访问权限限制,例如:访问 private
字段、静态字段等。常用的反射操作包括:
- 获取字段 :使用
getDeclaredField()
或getField()
获取字段。 - 访问字段的值 :使用
Field.get()
方法访问字段的值。 - 修改字段的值 :使用
Field.set()
方法修改字段的值。 - 访问静态字段 :静态字段是属于类的,因此可以通过
null
来表示该字段不依赖于实例。
通过反射,我们可以更加灵活地处理对象的成员,尤其是在动态创建和操作类实例、框架设计、序列化等方面,反射提供了极大的便利。然而,反射也带来了性能开销,因此应根据实际需求合理使用反射。所以说,并不能一味说反射就是最牛的,各有利弊,需恰当适用才是最强的。
... ...
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
... ...
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!