3

在 Java 中,在运行时可以使用反射访问私有字段,也可以使用反射访问私有嵌套/内部类(例如,请参见此处)。是否有任何特定的技术原因或任何一般的设计理念可以解释为什么 Java 会这样?我不知道,但从阅读这篇文章来看,它看起来像 C#/.NET,至少在某些配置中,同样的事情是不可能的。Java是否也具有这种灵活性?是否有任何 JVM 实现无法做到这一点?

当然,即使 Java 不允许通过反射访问私有字段,您也可以随时编写自己的运行时来做任何您喜欢的事情。或者您可以修改二进制 .jar/.class 文件并更改访问修饰符(我认为这是可能的)。

因此,Java 的设计者似乎必须从三种可能性中进行选择:

  1. 允许直接访问私有字段...可能带有警告。
  2. 不允许直接访问私有字段,但允许使用反射访问私有字段。
  3. 不允许直接访问私有字段,也不允许使用反射访问私有字段。访问私有字段的唯一方法是更改​​运行时或离线修改二进制 .jar/.class 文件。

选择中间的对我来说似乎是任意的……如果目标是让它尽可能不方便,选择 3 是最好的。如果目标是不给无论如何都无法真正预防的事情增加人为的不便,那么 1 是最好的。

是否有关于语言或运行时的某些信息通知或强制决定采取选择 2?

4

2 回答 2

2

从某种意义上说,使用反射不正是您在#1 中寻找的警告吗?

有时使用反射可以为其他乏味的问题提供一些优雅的解决方案,GSON 库如何创建和填充对象就是一个很好的例子。“正常”代码不应该访问这些私有字段,使用反射可以让您这样做,并通过异常处理和权限修改的所有必要开销来明确这不是在一般情况下要做的事情。

反射提供了比简单地访问私有字段更多的功能。它允许您在运行时检查有关在编译时不知道的类和对象的数据,并使用它们来调用方法和访问编译代码时不存在的字段。该行为的一个子集是私有访问。

所以是的,Java 设计者本可以为私有访问创建某种语法,但他们还需要创建反射,这是访问私有数据的一种更合乎逻辑和更强大的方式;同时非常清楚(如果只是因为它很复杂)应该谨慎使用这种行为。对我来说,简单地打电话object.privates.field或类似的事情并不意味着同样的严重性。

于 2013-08-14T20:23:04.457 回答
0

有时您需要访问私有字段以进行单元测试。例如在一个内部使用但不应该直接调用的类中测试小的私有函数。其他时候,您可能想要检查内部数据结构是否包含正确的数据。

如果您出于其他原因使用反射作为访问私有数据的一种方式,您可能必须想出一个很好的理由这样做,因为大多数审查您的代码(如果有的话)的人可能会注意到并且会出现红色标志(该字段出于某种原因是私有的,对吗?)。

选择 2 可能是为了允许使用反射(可以在非调试版本中禁用)。

于 2013-08-14T20:21:46.403 回答