Field类的setAccessible()方法

      或许标题上说的并不是很准确,setAccessible方法准确得说是从AccessibleObject类继承过来的,不过这么说也没什么错,就不要纠结这个了,让我们进入主题

     setAccessible方法是干什么用的呢让我们来看一段代码吧

  public class User {
private String name;
public User(String name) {
this.name = name;
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}



}


测试:

import java.lang.reflect.Field;


public class Demo {
public static void main(String[] args) throws Exception {  
   Class clazz = User.class;
       User u = new User("小明");
       for (Field f : clazz.getDeclaredFields()) {  
           System.out.println(f.isAccessible());//这里的结果是false
           f.setAccessible(true);
           System.out.println(f.getName()+":"+f.get(u));
       }  
 
   }  


}


通过运行以上代码,我们发现  System.out.println(f.isAccessible())这一句打印结果是"false",从字面上理解是说该字段不能被访问,但是为了保险起见我们还是去看一下源代码(Java有的时候就是比较坑,不一定能够见名知意,我们还是保险点比较好,虽然不算是做学问,但是学习的态度还是一丝不苟比较好),首先我们去掉f.setAccessible(true);

然后在 System.out.println(f.getName()+":"+f.get(u));这行打断点,但是发现不了问题,经过检查发现getName()这个方法并不抛异常,也就是是就算没有加f.setAccessible(true);

也可以获得name,抛异常的是f.get(u);这句话,我找到Field中的get(Object obj)方法,发现有这么一句

if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
            }
        }

这里的override就是我们用setAccessible设置的值,但是接下来就坑爹了Reflection以及其他几个类的源码不在jdk自带的源码中,找了半天才找到sun的源代码,导入源代码(最好将sun的源代码和java的放在一个文件夹里,不然一次只能导入一个源代码,要来回切换,比较麻烦)

然后我们debug定位到了Reflection类的ensureMemberAccess方法如图:


图中有一个verifyMemberAccess方法,这就是抛出异常的方法,进入该方法直接到了 boolean successSoFar = false;然后就return false了,因此抛出了IllegalAccessException异常,也就是说我们得出结论当isAccessible()的结果是false时不允许通过反射访问该字段


结论:当isAccessible()的结果是false时不允许通过反射访问该字段

当该字段时private修饰时isAccessible()得到的值是false,必须要改成true才可以访问


所以     f.setAccessible(true);得作用就是让我们在用反射时访问私有变量

  • 17
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值