反射setAccessible,java反射调用set方法

  反射setAccessible,java反射调用set方法

  00-1010摘要1。什么是Java的访问检查2。setAccessible()方法介绍:当我使用Field类的对象访问我自定义的Employee类对象的name字段时,抛出了一个异常illegalAccessException。查询的原因是:在访问名称域的时候,Java检查了访问,发现该域被private修饰,不能直接访问,于是抛出异常。

  00-1010本文首先详细介绍了访问检查的概念,然后介绍了关于反射的运行时访问检查,并说明了可能出现的问题。最后,介绍了运行时访问检查可以被setAccessible方法屏蔽或禁用。开始放吧~ ~

  

目录
访问检查,就是查看成员属性、成员方法的使用是否符合访问权限(public、protected、default、private)。

  太理论化了。简单来说,如果一个类的成员(属性或方法)的访问权限是私有的,那么该成员只能在当前类中使用;如果一个类的成员的访问权限是public,那么这个成员可以在任何类中使用;如果一个类成员的访问权限是default,那么这个成员只能在同一个包下的类中使用;如果类成员的访问权限受到保护,则该成员可以在同一包下的类中使用,也可以在其他包下的类的子类中使用。

  如果一个类的成员的访问权限是默认的,但是你在另一个包中使用成员当编译时,编译器会进行访问检查,你发现这个成员的使用与给定的访问权限不一致,那么你将报告一个错误。

  例如,在com.example包下创建People类,它有四个成员变量。在com.example.app的包下(不同于com.example的包),使用People类的四个成员变量。

  包com.example包com.examplepublic class People { private int private var=1;int default var=2;protected int protected var=3;public int public var=4;}打包com . example . app;导入com . example . people;公共类test main { public static void main(String[]args){ People p=new People();system . out . println(p . private var);system . out . println(p . default var);system . out . println(p . protected var);system . out . println(p . public var);}}编译后提示,publicVar的使用符合public的访问权限,所以没有错误。

  相信大家都明白什么是准入检查。那么,反射对象的访问检查呢?

  在反射中,类的成员属性、成员方法和构造函数被抽象为字段、方法和构造函数类。

  我们可以使用Field来访问对象的成员属性,成员属性的访问权限对于编译器来说是未知的,只有在运行时才知道。因此,对反射对象(如字段)的访问权限的检查只能给虚拟机。

  如果在虚拟机运行时,它发现成员的使用与给定的访问权限不一致,如下面的代码所示

  打包com . example . app;导入com . example . people;导入Java . lang . reflect . field;公共类test main { public static void main(String[]args)抛出NoSuchFieldException,IllegalAccessException { People p=new People();class cl=p . getclass();//使用反射访问private修饰的成员变量字段f=cl . getdeclaredfield( private var )system . out . println(f . get(p));}}运行时抛出异常:Java . lang . illegalaccessexception。

  er">

  综上,访问检查可以时编译器在编译时进行或者虚拟机在运行时进行(主要是针对反射)

  

  

二、 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()方法的文章就介绍到这了,更多相关Java反射setAccessible()内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: