大家好,又见面了,我是全栈君。
大家都知道正常的调用是不可以访问对象的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。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/108659.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...