Java反射获取private属性和方法(子类,父类,祖先....)
发布日期:2025-04-02 02:37:22 浏览次数:9 分类:精选文章

本文共 2423 字,大约阅读时间需要 8 分钟。

Java反射获取私有属性和方法(子类、父类、祖先等)

反射在Java编程中扮演着重要角色,特别是在处理私有属性和方法时,它提供了强大的灵活性。通过反射,我们可以访问一些在通常情况下无法直接访问的元素。然而,反射的使用需要谨慎,其潜在危险性可能导致代码安全性问题。

先来看一个例子:String可变还是不可变?

通常情况下,String类被认为是不可变的。这是因为字符串实际上使用一个final char数组来存储字符数据,带有private访问修饰符。这种结构使得字符串的可变性被严格限制。但是,让我们深入探讨这个问题。

首先,在运行时,字符串"abc"被存储为一个指向char数组的引用。该数组存储在String对象的"值"属性中。我们可以通过反射机制获取到这个私有属性,并绕过语言层面的常见约束。

反射用法

灭一灭百。反射提供了强大的操作类的能力。通过反射,我们可以访问运行时类信息,修改属性值,执行静态方法,创建对象等。这种能力使得程序具有了更大的灵活性。

下面是一段代码示例:

static void getClassFieldAndMethod(Class cur_class) { String class_name = cur_class.getName(); Field[] obj_fields = cur_class.getDeclaredFields(); for (Field field : obj_fields) { if (field.isAccessible()) { System.out.println(class_name + ": " + field.getName()); } try { field.setAccessible(true); System.out.println(class_name + ": " + field.getName()); } catch (SecurityException e) { e.printStackTrace(); } } Method[] methods = cur_class.getDeclaredMethods(); for (Method method : methods) { try { method.setAccessible(true); System.out.println(class_name + ": " + method.getName()); } catch (SecurityException e) { e.printStackTrace(); } } if (cur_class.getSuperclass() != null) { getClassFieldAndMethod(cur_class.getSuperclass()); } }

代码解释:

  • 取得当前类的名称。
  • 遍历该类的所有非传递字段,并输出每个字段的名称。
  • 对于每个方法,调用setAccessible方法,使其变得可访问。
  • 如果类有父类直到Object类,递归处理父类。
  • 类似的逻辑也可以用于获取对象属性和方法。

    伪原

    这段代码输入一个Class对象,递归输出该类的父类、祖父类直到Object类的所有方法和域。你可以使用它来查看类的具体实现,或者绕过常见的程序设计约束。

    注:请谨慎使用反射操作,因为它可能导致一些不规范的行为,例如绕过Java安全机制,形成漏洞或隐藏的副作用。

    postscript

    关于intern()方法的实现细节,它是通过Stringthis cansThrownBy Chester名字符池来工作的。这意味着在调用intern()时,字符串会被存储在类String管理的常量池中。

    官方文档中,intern()方法的注释已详细说明了其工作原理:

  • 检查常量池中是否存在一个与当前字符串相等的对象。
  • 如果存在,返回该对象引用。
  • 如果不存在,创建一个新的字符串实例,将其存储在常量池中,并返回新的对象。
  • 通过上述分析,我们可以看出语句执行过程中发生了什么事情。如果你希望为这个Example进行更深入的分析,你可能需要参考JVM的一些内部实现细节。

    好了,回到我们的变量修改示例:

    a = "abc" valueFieldString.setAccessible(true) char[] value = (char[]) valueFieldString.get(a) value[2] = '@'

    在这种情况下,String对象的"值"属性被修改为包含字符'@'。然而,尽管字符的值被修改了,字符串对象本身仍然保持不变,仍然指向常量池中的那个对象。

    那么,问题来了:

    b = "abc" "abc".equals(b) ?

    这里的关键点在于String对象的值属性与字符串整体的可变性。通过我们的修改,可以看出String对象的字符数组发生了变化,而字符串整体的行为却没有和直接修改常量池中的字符串一样。

    简单来说,即使你修改了字符串的内部存储内容,字符串本身仍然与常量池中的那个对象绑定。因此,修改后的字符串和原始的字符串在引用上是相同的,但在内容上是不同的。

    这样,当你创建一个新的字符串实例的时候,虽然在常量池中会新增一个新的字符串,但原有的字符串对象不会受到影响。

    现在,再回到反射的反向介绍。通过反射机制,你可以修改实例中的域值,甚至创建新的动态方法。这使得反射非常灵活,也非常危险。在编写代码时,确保反射操作是安全和可靠的至关重要。

    总之,反射提供了对Java对象模型的高度灵活性,使开发者能够实现复杂的功能。然而,你需要谨慎对待反射,因为它可能导致意想不到的后果。

    如果你已经理解了上述内容,请可以跳到下一个Section,探讨反射的实际用法。需要注意的是,反射是一项强大的工具,遇到不良使用可能导致严重后果。

    上一篇:java反射(1):Class代表类
    下一篇:java反射的使用

    发表评论

    最新留言

    能坚持,总会有不一样的收获!
    [***.219.124.196]2025年05月03日 22时51分22秒

    关于作者

        喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
    -- 愿君每日到此一游!

    推荐文章

    02-Docker镜像分类及操作秘籍,轻松掌握导出、导入、删除 2025-03-28
    04-docker-commit构建自定义镜像 2025-03-28
    04-docker系列-commit构建自定义镜像 2025-03-28
    05-docker系列-使用dockerfile构建镜像 2025-03-28
    09-docker系列-docker网络你了解多少(下) 2025-03-28
    10-docker系列-docker文件共享和特权模式 2025-03-28
    #C2#S2.2~S2.3# 加入 factory/objection/virtual interface 机制 2025-03-28
    #C8# UVM中的factory机制 #S8.1.1# OOP 语言三大特性 systemverilog的支持 2025-03-28
    #C8# UVM中的factory机制 #S8.1.4# 约束的重载 2025-03-28
    #C8# UVM中的factory机制 #S8.2.3# 重载sequence哪些情形 2025-03-29
    #C8# UVM中的factory机制 #S8.4.1# factory机制的实现 2025-03-29
    900行c语言贪吃蛇,原生js实现的贪吃蛇网页版游戏完整实例 2025-03-29
    ado读取多条oracle数据,Oracle ADO数据存取 2025-03-29
    android fastjson漏洞_初识Fastjson漏洞(环境搭建及漏洞复现) 2025-03-29
    asp.mvc 4项目发布文件目录结构_如何用SpringBoot(2.3.3版本)快速搭建一个项目?文末有小彩蛋... 2025-03-29
    aspen串联反应怎么输入_如何进步提升串联谐振试验装置的稳定性 2025-03-29
    c++ string取子串_Integer与String的设计哲学 2025-03-29
    c++ 数组批量赋值_数组之间不能赋值?穿个马甲吧! 2025-03-29
    cad模糊查询符号_mysql 正则模式和like模糊查询 2025-03-29
    continue可以用if判断里面吗_谁能说说if()else()里的continue是干嘛的? 2025-03-29