Java反射的setAccessible()方法怎么使用
本篇内容介绍了“Java反射的setAccessible()方法怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
一、 什么是Java的访问检查
访问检查,就是查看成员属性、成员方法的使用是否符合访问权限(public、protected、default、private)。
有点太理论化了,简单来说,如果一个类的成员(属性或者方法)的访问权限是private,那么该成员只能在当前类中使用;如果一个类的成员的访问权限是public,那么该成员可以在任意类中使用;如果一个类的成员的访问权限是default,那么该成员只能在同一个包下面的类中使用;如果一个类的成员的访问权限是protected,那么该成员可以在同一个包下面的类中和其他包下面的该类的子类中使用。
如果,类的成员的访问权限是default,你却在另一个包中使用了该成员,当编译时,编译器会进行访问检查,发现成员的使用与给定的访问权限不一致,因此会报错。
举个例子,在com.example包下创建People类,有四个成员变量。在com.example.app包下(它是不同于com.example的包)下,使用People类的四个成员变量。
package com.example;package com.example;public class People { private int privateVar = 1; int defaultVar = 2; protected int protectedVar = 3; public int publicVar = 4;}package com.example.app;import com.example.People;public class TestMain { public static void main(String[] args) { People p = new People(); System.out.println(p.privateVar); System.out.println(p.defaultVar); System.out.println(p.protectedVar); System.out.println(p.publicVar); }}
编译后提示,publicVar的使用符合public的访问权限,所以没有出错。
相信大家都理解了访问检查是什么,那么,反射对象的访问检查是怎么的呢?
一个类的成员属性、成员方法、构造函数,在反射中分别被抽象为Field、Method、Counstructor类。
我们可以使用Field访问对象的成员属性,成员属性的访问权限,编译器是不知道的,只有运行时才知道。因此对于反射对象(例如Field)访问权限的检查只能交给虚拟机。
如果,虚拟机在运行时,发现成员的使用与给定的访问权限不一致,如下代码
package com.example.app;import com.example.People;import java.lang.reflect.Field;public class TestMain { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { People p = new People(); Class cl = p.getClass(); // 利用反射访问private修饰的成员变量 Field f = cl.getDeclaredField("privateVar") System.out.println(f.get(p)); }}
运行时,抛出异常:java.lang.IllegalAccessException
综上,访问检查可以时编译器在编译时进行或者虚拟机在运行时进行(主要是针对反射)
二、 setAccessible() 方法介绍
setAccessible(boolean flag)
方法是AccessibleObject类中的一个方法,它是Field、 Method、Constructor的公共父类。当Field、Method或Constructor (三者都是反射对象)分别用于设置字段(set(Object obj, Object value)
)或获取字段(get(Object obj)
)、调用方法(invoke(Object obj, Object... args)
)或创建和初始化类的新实例(newInstance(Object... initargs)
)时,将执行运行时访问检查。
引用自《Java核心技术 第十版》
注意:方法名setAccessible很容易让人产生误解,给人的感觉是设置了成员的可访问性,例如,觉得public修饰的成员是任意类都可以访问的,所以可访问标志是true;觉得private修饰的成员只有本类可以访问,所以可访问标志是false。其实不然,不管是什么访问权限,其可访问标志的值都为false。
测试代码如下:
package com.example.app;import com.example.People;import java.lang.reflect.Field;public class TestMain { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { People p = new People(); Class cl = p.getClass(); // 打印输出所有成员变量的名字及可访问标志 for (Field f : cl.getDeclaredFields()) { System.out.println(f.getName() + ": " + f.isAccessible()); } }}
输入结果:
上面中的API说得很清楚,这个可访问标志表示是否屏蔽Java语言的访问检查,默认值是false,(上面已经测试)
可以通过setAccessible(true)
修改默认值,如此会屏蔽Java语言的(运行时)访问检查,使得对象的私有成员可以访问,而不报错。
package com.example.app;import com.example.People;import java.lang.reflect.Field;public class TestMain { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { People p = new People(); Class cl = p.getClass(); for (Field f : cl.getDeclaredFields()) { //屏蔽对象的访问检查 f.setAccessible(true); // 访问不符合访问权限的成员属性 System.out.println(f.getName() + " = " + f.get(p)); } }}
输入结果:
“Java反射的setAccessible()方法怎么使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341