Reflection API 是否破坏了数据封装的初衷?

2023-11-25

最近我遇到了 Reflection API,令我惊讶的是我们可以访问甚至更改私有变量。我尝试了以下代码

import java.lang.reflect.Field;

public class SomeClass{
    private String name = "John";
}

public class Test{
    public static void main(String args[]) throws Exception {
        SomeClass myClass = new SomeClass();

        Field fs = myClass.getClass().getDeclaredField("name");
        fs.setAccessible(true);

        System.out.println("Variable is " + fs.getName() + " and value is "
                + fs.get(myClass));

        fs.set(myClass, "Sam");
        System.out.println("Variable is " + fs.getName() + " and value is "
                + fs.get(myClass));
    }
}

我得到以下输出。

Variable is name and value is John
Variable is name and value is Sam

我们说Java是一种面向对象的语言,它的主要特点是数据封装、继承、多态性……等等。反射API不是改变了数据封装的目的吗?为什么我们必须使用Reflection API?我在一些网站上读到它可以用于测试目的,但根据我的说法,模块已经过测试,并且可以使用 JUnit 测试用例轻松完成。那么谁能解释一下为什么我们会有这样的黑客行为呢?


反射 API 不是改变了数据封装的目的吗?

是和不是。

  • 是的,反射 API 的一些用途can破坏数据封装。
  • 不,并非反射 API 的所有用途do破坏数据封装。事实上,明智的程序员只会在有充分理由时才通过反射 API 来打破封装。
  • 不,反射 API 不会改变purpose的数据封装。这purpose数据封装的原理保持不变……即使有人故意破坏它。

为什么我们必须使用Reflection API?

many反射的用途DO NOT破坏封装;例如使用反射来找出类有哪些超类型、有哪些注释、有哪些成员、调用可访问的方法和构造函数、读取和更新可访问的字段等。

在某些情况下,使用破坏封装的反射类型是可以接受的(在不同程度上):

  • 您可能需要查看封装类型的内部(例如访问/修改私有字段)作为实现某些单元测试的最简单方法(或唯一方法)。

  • 某些形式的依赖注入(又名 IoC)、序列化和持久化需要访问和/或更新私有字段。

  • 偶尔,您需要打破封装来解决某些类中无法修复的错误。

我在一些网站上读到它可以用于测试目的,但根据我的说法,模块已经过测试,并且可以使用 JUnit 测试用例轻松完成。那么谁能解释一下为什么我们会有这样的黑客行为呢?

这取决于您的班级设计。设计为可测试的类要么可以在不需要访问“私有”状态的情况下进行测试,要么将公开该状态(例如protectedgetter)以允许测试。如果类不这样做,那么 JUnit 测试可能需要使用反射来查看抽象内部。

这是不可取的(IMO),但是如果您正在为某人编写的类编写单元测试,并且您无法“调整”API 来提高可测试性,那么您可能必须在使用反射或根本不测试之间做出选择。


最重要的是,数据封装是我们努力实现的理想(在 Java 中),但在某些情况下,实际正确的做法是破坏它或忽略它。

请注意,并非所有 OO 语言都像 Java 一样支持强数据封装。例如,Python 和 Javascript 无疑都是面向对象的语言,但两者都使一个类可以轻松访问和修改另一个类的对象状态……甚至更改其他类的行为。强数据抽象并不是每个人对面向对象含义的看法的核心。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Reflection API 是否破坏了数据封装的初衷? 的相关文章

  • 内存不一致与线程交错有何不同?

    我正在编写一个多线程程序 正在研究是否应该使用volatile对于我的布尔标志 关于并发性的文档 oracle Trail 没有解释任何关于memory consistency errors以外 当不同的线程有内存一致性错误时 就会发生内存
  • 为什么尝试使用 Hamcrest 的 hasItems 的代码无法编译?

    为什么这个不能编译 哦 怎么办 import static org junit Assert assertThat import static org junit matchers JUnitMatchers hasItems ArrayL
  • 在tomcat中显示Spring-security的SQL错误

    我使用 spring security 框架创建了一个 Web 应用程序 我设置了一个数据库来存储用户及其角色 但 tomcat 给出以下错误 17 sep 2010 11 56 14 org springframework beans f
  • iText7:如何获取段落的实际宽度

    在添加到文档之前 我需要知道段落的宽度 以磅为单位 我在这里搜索并找到了 Alexey 关于段落高度的答案 所以我用宽度做了它 但它不起作用 无论段落有多长 始终返回矩形的宽度 我尝试了这段代码 private float getRealP
  • 如何将 Excel 中的图表导出为图形

    我有一系列 Excel 电子表格 每个电子表格至少包含一页数据和一页根据数据创建的图表 我需要捕获 不从数据中重新生成 将现有图表作为网络友好图像 这可以通过 Java 或 Net 实现吗 我知道 POI 的东西 Java 不会这样做 或者
  • javax.naming.NameNotFoundException

    我正在 JBoss 5 容器中运行 ejb 示例 我正在使用一个例子从这里开始 第一部分 http www roseindia net jboss jboss 3 2 shtml 在示例中 我在 JBoss 中部署了 bean 并在 Tom
  • Spring - 两种不同的 POST 方法,具有相同的 URL,但生成的内容类型不同

    我有以下控制器 RequiredArgsConstructor RestController public class OwnerViewController implements ApiOwnerViewController privat
  • 如何使 java.text.NumberFormat 将 0.0d 格式设置为“0”而不是“+0”?

    需要带符号的结果 0 0d 除外 IE 123 45d gt 123 45 123 45d gt 123 45 0 0d gt 0 我调用format setPositivePrefix 在 DecimalFormat 的实例上 强制结果中
  • 正则表达式或用单个空格替换多个空格的方法

    你能告诉我有没有办法在java或spring中用单个空格替换多个空格 有相同的 stringUtils 函数吗 like 1 test test test test 2 test test test test 3 test test tes
  • 设置 MetaspaceSize 的指南 - java 8

    64 位服务器的 MetaspaceSize 默认值是多少 我在官方文档中没有找到它 我观察到 在服务器 JVM 进程中 GC 频率有时会变高并持续增长 如果我重新启动服务几次 它就会恢复稳定 我认为这是由于 JRE 升级造成的 JVM 堆
  • 清理 IntelliJ 中构建的 Play 框架

    我有一个拼写错误conf routes文件导致 Play Framework 生成错误命名的类 重建项目并运行Invalidate Caches并没有解决 IntelliJ 中的问题 当我手动运行时重新生成了不正确的类文件play clea
  • kafka消费端Offsets的一致性

    我有复制因子为 3 的卡夫卡主题min insync replicas 2 一个向该主题发送 X 条消息的生产者acks all 一段时间后 1 分钟内 在所有消息发送到主题后 将使用 java kafka 客户端为此主题创建新的消费者 使
  • 如何自定义 JFrame 上的标题栏?

    我想在我的 Java Swing 桌面应用程序中拥有一个自定义的标题栏 最好的方法是什么 我可以通过在 JFrame 的构造函数中使用以下代码来使用 Swing 标题栏 this setUndecorated true this getRo
  • 在单独的模块中使用 Spring AOP 方面

    我在一个 Maven 项目模块中有一个方面 com x NiceAspect 在一个单独的 Maven 模块中有一个类 com x NiceClass 这些模块具有相同的 POM 父级 共同创建一个项目 我想要实现的目标是拥有一个通用的方面
  • 具有多个注释的方法上的 AspectJ 切入点

    使用加载时编织 纯 AspectJ 我们有2个注释 Time and Count 以及一些带注释的方法 Time name myMethod1Time Count name myMethod1Count public void myMeth
  • Kotlin 中的枚举类对于 Android 来说是否像 Java 中那样“昂贵”?

    Are EnumKotlin 中的类对于 Android 来说 昂贵 就像 Java 一样 还可以用吗 IntDefs or StringDefs在科特林 当我将 Kotlin Enum 类反编译为 Java 类时 底层仍然使用了 Java
  • Spring Oauth2. DaoAuthenticationProvider 中未设置密码编码器

    我对 Spring Oauth 和 Spring Security 很陌生 我正在尝试在我的项目中使用 client credentials 流程 现在 我设法使用自己的 CustomDetailsS ervice 来从系统中已存在的数据库
  • SWIG C 函数指针和 JAVA

    我有一些 C 代码 其中一个方法有一个函数指针作为参数 我正在尝试在我的 Android 应用程序中使用 C 代码 我决定使用 SWIG 来完成生成我需要的 java 文件的所有工作 一切都适用于常规函数 没有函数指针作为参数的函数 但我不
  • JAXB 枚举字段未序列化

    我有以下课程 package dictionary import java io Serializable import java util Objects import javax xml bind annotation XmlEleme
  • JAAS keytab 配置的相对路径

    我有一个系统 其中 NET 客户端使用 Kerberos 针对 Java 服务器进行身份验证 一切正常 但我正在尝试改进服务器配置 目前一个keytab根目录中需要文件C 因为我的jaas配置文件看起来像这样 Server com sun

随机推荐

  • 如何在PHP中限制文件上传类型的文件大小?

    我有一个上传表单 正在检查文件大小和文件类型 以将上传的文件限制为 2 MB 文件类型为 pdf jpg gif 或 png 我的目标是 如果用户违反这些规则之一 则向他们显示一条警报消息 有四种情况 正确尺寸 正确类型 工作 正确尺寸 错
  • 带硬件加速的画布抗锯齿(Android API 11 及更高版本)

    我有一个简单的位图 我在画布中绘制并使用矩阵旋转 我遇到的问题是 使用硬件加速时 边缘在旋转时不会消除锯齿 这在关闭硬件加速的情况下完美运行 当然 像 setDrawFilter 这样的东西是没有用的 因为当硬件加速打开时它们会被忽略 ca
  • javascript中如何在不同html页面之间传递变量值

    我想传递选择的值项目清单到另一个页面 意味着如果我从列表中选择 abc 那么这个 abc 值会传递到下一个 html 表单 它应该只打开该配置文件页面 有什么方法可以在不同的 html 页面之间使用此变量 ui li icon li cli
  • 为什么 C# 中不调用所有静态构造函数(即父类的静态构造函数)?

    我有三节课 Base Derived and Final Derived源自于Base and Final源自于Derived 所有三个类都有一个静态构造函数 班级Derived作为一个名为的公共静态方法Setup 当我打电话时Final
  • Jenkins Groovy 构建后脚本用函数评估文件

    我正在使用以下代码构建后我的詹金斯工作步骤 evaluate new File Set BuildBadge groovy 因此 如果确实如此 它就会成功运行脚本not包含函数 如果在脚本中我定义了一个function例如 def addS
  • 带有整数的 if 语句[重复]

    这个问题在这里已经有答案了 我是 Java 新手 我正在寻找家庭作业方面的帮助 我不会发布我最初这样做的完整代码 但我认为这不会帮助我学习它 我有一个与类一起使用的程序 我有一个将验证选择的类 一个包含我的 setter 和 getter
  • Linux 上的 PHP 5.4:如何连接 MS SQL Server 2008?

    我有一台 Linux 服务器 Debian 6 安装了 Apache 2 2 和 PHP 5 4 我需要将我的应用程序与 MS SQL Server 2008 连接 我的应用程序使用 Zend Framework 1 11 和字符集 UTF
  • 如何在选择文本后弹出窗口?

    我似乎无法弄清楚这一点 我有一个 div 里面有一些文本 当用户选择其中的一部分 完全随机 无论他们想要什么 时 我希望出现一个小弹出窗口 其中包含文本 要启动弹出窗口 我可以这样做吗 textdiv click function 但是我怎
  • 出现“内容丢失”的 Turbo Frame 错误

    我正在尝试在 Rails 应用程序中使用turbo frame tag 来管理一些任务 我为我的任务创建了一个脚手架 我将要使用的页面包装在 Turbo 框架标签内 如下所示 h1 New task h1 br div gt div
  • 从 scala 脚本退出 Spark-shell

    我正在使用这个命令来运行 scala 脚本 spark shell i test scala 在脚本执行结束时 我仍然看到 Spark shell 正在运行 我在 test scala 脚本中使用了 q quit 来尝试退出 但它不起作用
  • BasicHTTPServer、SimpleHTTPServer 和并发

    我正在使用 python BasicHTTPServer 和 SimpleHTTPServer 编写一个小型 Web 服务器用于测试目的 看起来它一次只处理一个请求 有什么办法可以让它更快一点 而又不会太麻烦吗 基本上我的代码如下所示 我想
  • SessionNotCreatedException:消息:会话未创建:尽管安装了 Chrome v74,但此版本的 ChromeDriver 仅支持 Chrome 版本 74

    我开始在 python 中使用 selenium 当我尝试运行此代码时 它只是弹出一个错误 表明此版本的 chromedriver 仅支持 74 版本的 chrome 但我已经从这里下载了 74 版本 https chromedriver
  • 注释使私有方法仅对测试类公开[重复]

    这个问题在这里已经有答案了 谁有解决这个共同需求的解决方案 我的应用程序中有一个课程 有些方法是公共的 因为它们是 api 的一部分 有些是私有的 因为它们供内部使用 使内部流程更具可读性 现在 假设我想编写一个单元测试 或者更像是一个集成
  • 文本区域最大长度不起作用

    我想设置文本区域的最大长度 我使用以下代码进行相同的操作 但它不起作用
  • 使用特征矩阵构建 3D 结构的最有效选项

    我的代码需要 3D 矩阵 数组结构 现在我的矩阵和向量都依赖 Eigen 现在我正在使用创建一个 3D 结构new MatrixXd cube new MatrixXd 60 for int i i lt 60 i cube i Matri
  • ASP.NET MVC 环境的推荐单元测试书籍 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我需要推荐一本与 ASP NET MVC 一起使用的优秀单元测试书籍 根据您实际阅读和使用的书籍 您的圣经 您推荐什么 似乎所有较新的 ASP NE
  • 使用闪亮的应用程序创建反应式数据框

    我试图让这个反应返回一个我可以用绘图操作的数据帧 avghour lt reactive result lt data frame start date lt as numeric unlist input i6 1 end date lt
  • 无法加载 rJava,因为无法加载共享库

    我一直在努力在 R 中加载 rJava 包 我收到以下消息 gt library rJava Error in inDL x as logical local as logical now unable to load shared lib
  • SQL Server:找出导致 TSQL 失败的行 (SSIS)

    SQL Server 2005 问题 我正在开展一个数据转换项目 其中我要获取 80k 多行并将它们从一个表移动到另一个表 当我运行 TSQL 时 它会出现各种与转换类型或其他相关的错误 有没有办法找出导致错误的行 UPDATE 我正在执行
  • Reflection API 是否破坏了数据封装的初衷?

    最近我遇到了 Reflection API 令我惊讶的是我们可以访问甚至更改私有变量 我尝试了以下代码 import java lang reflect Field public class SomeClass private String