Java反射学习总结二(用反射调用对象的私有属性和方法)
大家都知道正常的调用是不可以访问对象的private修饰的属性和方法的,这也是Java的封装性原则。
但是有没有方法可以强制去访问对象的private修饰的属性和方法呢?那就是用反射!(这个可能在面试题中被问到哦)
接下来就来看看是如何实现的:
我们先去jdk里看一下描述属性的类Field,和方法的类Method:
- java.lang.Object
-
- java.lang.reflect.AccessibleObject
-
- java.lang.reflect.Field
-
- java.lang.Object
-
- java.lang.reflect.AccessibleObject
-
- java.lang.reflect.Method
-
可以看到这两个类有个共通的特点,就是他们都继承自java.lang.reflect.AccessibleObject这个类,我们好好看看这个类的描述
- java.lang.Object
-
- java.lang.reflect.AccessibleObject
- All Implemented Interfaces:
- AnnotatedElement
- Direct Known Subclasses:
- Constructor, Field, Method
public class AccessibleObject extends Object implements AnnotatedElement
The AccessibleObject class is the base class for Field, Method and Constructor objects. It provides the ability to flag a reflected object as suppressing default Java language access control checks when it is used. The access checks--for public, default (package) access, protected, and private members--are performed when Fields, Methods or Constructors are used to set or get fields, to invoke methods, or to create and initialize new instances of classes, respectively.
大致意思就是:
这个AccessibleObject类是Field, Method and Constructor对象的一个父类,他可以让一个反射对象去禁止Java语言的访问控制检测。控制检测有public, default (package) access, protected, and private。。。blah blah blah。。。
这里我贴出控制访问控制检测的这个方法:(这个类里还有一些相关的方法,有兴趣的大家可以自己去看看)
setAccessible
public void setAccessible(boolean flag) throws SecurityException
accessible
flag for this object to the indicated boolean value. A value of true
indicates that the reflected object should suppress Java language access checking when it is used. A value of false
indicates that the reflected object should enforce Java language access checks.大致意思:
设置标志去指示对象的boolean值,如果是true则禁止java访问控制检查,如果是false则强制反射对象使用java访问控制检查
知道了这个方法就可以做一个小例子测试一下啦。
下面这个例子很简单,就是定义一个dog类,里面有个private的属性dogName,和private的方法say。
main函数里用反射先去修改dogName,然后在调用say方法打印出来:
- public class Test2 {
- public static void main(String[] args) throws Exception {
- //获得Dog类的Class对象
- Class<?> classType = Class.forName("Dog");
- //生成对象的实例
- Object obj = classType.newInstance();
- //取得dogName属性
- Field dogName = classType.getDeclaredField("dogName");
- //禁止Field的访问控制检查
- dogName.setAccessible(true);
- //将Field的值设为“Xiao Qiang”
- dogName.set(obj, "Xiao Qiang");
- //取得say()方法
- Method say = classType.getDeclaredMethod("say", new Class[]{});
- //禁止say方法的访问控制检查
- say.setAccessible(true);
- //调用say方法
- say.invoke(obj, new Object[]{});
- }
- }
- class Dog {
- //私有的属性
- private String dogName = "Wang Cai";
- //私有的方法
- private void say() {
- System.out.println(dogName + ": Wang Wang");
- }
- }
输出结果:Xiao Qiang: Wang Wang
这里需要特别注意一个地方:
如果想用反射修改访问控制检查的话,获取Method和Field对象的时候一定要用getDeclaredField和getDeclaredMethod。不要用getField和getMethod。
虽然这两个方法的参数都是相同的,但不同点在于getMethod和getField只能获得public修饰的属性和方法。而getDeclared可以获取任何类型的属性和方法,因为这个例子要调用私有的属性和方法,所以要用getDeclaredXX。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
2014-02-14 把1000个随机数写入到文件中