java setaccessible_Java setAccessible() 方法

java setaccessible_Java setAccessible() 方法1 直接通过 Field 访问 private 对象会报错测试代码如下 publicvoidac Employeeempl newEmployee hrm 500 2000 11 11 for Fieldf employee getClass getDeclaredF try System out prin

1.直接通过 Field 访问 private 对象会报错

测试代码如下:

public void accessPrivateObjects(){

Employee employee = new Employee(“hrm”,500,2000,11,11);

for(Field f : employee.getClass().getDeclaredFields()){

try{

System.out.println(f.get(employee));

}catch (IllegalAccessException e){

e.printStackTrace();

}

}

}

public class Employee extends People{

private double salary;

private LocalDate hireDay;

}

报错:

java.lang.IllegalAccessException: class fiveChapter.FiveChapter cannot access a member of class fiveChapter.Employee with modifiers “private”

原因:

由于 salary 是一个私有域, 所以 get 方法将会抛出一个IllegalAccessException。只有利用 get 方法才能得到可访问域的值。除非拥有访问权限,否则Java 安全机制只允许査看任意对象有哪些域, 而不允许读取它们的值。

反射机制的默认行为受限于 Java 的访问控制。然而, 如果一个 Java 程序没有受到安全管理器的控制, 就可以覆盖访问控制。 为了达到这个目的, 需要调用 Field、 Method 或Constructor 对象的 setAccessible 方法。

–《Java核心技术 卷1 基础知识 原书第10版》P199

2.利用 setAccessible 访问私有对象的值

name属性为 Employee类的超类 People类的成员,getDeclaredFields()返回值不包括超类成员

getField()仅能获取类(及其父类可以自己测试) public属性成员

/

* 利用反射获取 private 域的值,不包含超类域

* 输出:500.0

* 2000-11-11

*/

public static void accessPrivateObjects(){

Employee employee = new Employee(“hrm”,500,2000,11,11);

for(Field f : employee.getClass().getDeclaredFields()){

f.setAccessible(true);

try{

System.out.println(f.get(employee));

}catch (IllegalAccessException e){

e.printStackTrace();

}

}

}

3.setAccessible方法分析

setAccessible为AccessibleObject 类中的一个方法,是它是 Field、 Method 和 Constructor 类的公共超类。这个特性是为调试、 持久存储和相似机制提供的。

因而想访问 Field、 Method 和 Constructor 的私有对象,均需 setAccessible。

public void setAccessible(boolean flag)

5e4abbce071b8e86707326b9fb1760bd.png

public static void setAccessible(AccessibleObject[] array, boolean flag)

5af427e824dbac6b67f99665daecd99e.png

4.可供任意类使用的通用 toString方法

其中使用getDeclaredFileds 获得所有的数据域, 然后使用 setAccessible 将所有的域设置为可访问的。 对于每个域,获得了名字和值。递归调用 toString方法, 将每个值转换成字符串。

public class ObjectAnalyzer {

private ArrayList visited = new ArrayList<>();

/

* 将对象转换为列出所有字段的字符串表示形式。

* @param object

* @return 包含对象类名以及所有字段名和值的字符串

*/

public String toString(Object object){

if(object == null) return “null”;

if(visited.contains(object)) return “…”;

visited.add(object);

Class cl = object.getClass();//返回一个Class类型的实例

//如果是 String 类直接返回对象

if(cl == String.class) return (String) object;

//如果该实例是数组

if(cl.isArray()){

//返回表示数组的组件类型的类 。 如果此类不表示数组类,则此方法返回null。

String r = cl.getComponentType() + “[]{“;

for(int i = 0; i < Array.getLength(object); i++){

if(i > 0) r+= “,”;

//返回指定数组对象中索引组件的值,即返回 object 数组对象索引 i 的值

Object val = Array.get(object,i);

//isPrimitive() 确定指定的类对象是否表示基本类型

if(cl.getComponentType().isPrimitive()) r += val;

else r += toString(val);

}

return r + “}”;

}

String r = cl.getName();

do{

r += “[“;

Field[] fields = cl.getDeclaredFields();

//设置可访问 private 对象的值

AccessibleObject.setAccessible(fields,true);

for(Field f : fields){

if(!Modifier.isStatic(f.getModifiers())){

if(!r.endsWith(“[“)) r += “,”;

r += f.getName() + “=”;

try{

//返回域所属类型的 Class 对象

Class t = f.getType();

Object val = f.get(object);

if(t.isPrimitive()) r += val;

else r += toString(val);

}catch (Exception e){

e.printStackTrace();

}

}

}

r += “]”;

cl = cl.getSuperclass();

}while (cl != null);

return r;

}

}

测试:

public void objectAnalyzerTest(){

ArrayList squares = new ArrayList<>();

for(int i = 1; i <= 5; i++){

squares.add(i * i);

}

System.out.println(new ObjectAnalyzer().toString(squares));

}

输出结果为:

java.util.ArrayList[elementData=class java.lang.Object[]{java.lang.Integer[value=1][][],java.lang.Integer[value=4][][],java.lang.Integer[value=9][][],java.lang.Integer[value=16][][],java.lang.Integer[value=25][][],null,null,null,null,null},size=5][modCount=5][][]

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/206359.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午3:53
下一篇 2026年3月19日 下午3:53


相关推荐

  • CentOS下安装Jmeter

    CentOS下安装Jmeter

    2021年6月1日
    95
  • Boost之LockFree[通俗易懂]

    Boost之LockFree[通俗易懂]Boost

    2022年7月19日
    16
  • 什么是静态代理和动态代理_静态ip和动态ip有什么区别

    什么是静态代理和动态代理_静态ip和动态ip有什么区别动态代理和静态代理到底有什么区别,好处在哪里?

    2025年11月10日
    8
  • vue-cli 3.0之跨域请求devServer代理配置

    vue-cli 3.0之跨域请求devServer代理配置概念什么是同源策略同源策略是一种约定 它是浏览器最核心也最基本的安全功能 如果缺少了同源策略 则浏览器的正常功能可能都会受到影响 可以说 Web 是构建在同源策略基础之上的 浏览器只是针对同源策略的一种实现 所谓同源是指 协议 域名 端口都相同什么是跨域跨域就是不同源 就是不满足协议 域名 端口都相同的约定如 看下面的链接是否与 http www test com index ht

    2026年3月19日
    2
  • 史丰收速算 蓝桥杯

    史丰收速算 蓝桥杯标题 史丰收速算 nbsp nbsp 史丰收速算法的革命性贡献是 从高位算起 预测进位 不需要九九表 彻底颠覆了传统手算 nbsp nbsp 速算的核心基础是 1 位数乘以多位数的乘法 nbsp nbsp 其中 乘以 7 是最复杂的 就以它为例 nbsp nbsp 因为 1 7 是个循环小数 0 如果多位数超过 就要进 1 nbsp nbsp 同理 2 7 3 7

    2026年3月19日
    2
  • 使用MyEclipse导入项目方法

    使用MyEclipse导入项目方法一 JDK 安装及环境变量设置检查安装配置教程二 使用 Myeclipse 导入项目 MyEclipse 乱码解决项目可以不在 MyWorkSpace 里面 1 选择 File gt Import 进入下图这个界面 2 点击 Next 进入下图 3 并选择项目路径 整个上层文件添加进来 点击确定 得到下图 可以看到刚添加的项目 4 点击 Finish 就完成了

    2026年3月19日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号