【问题标题】:Java: Telling JVM to treat all fields/methods as publicJava:告诉 JVM 将所有字段/方法视为公共的
【发布时间】:2019-04-13 16:06:48
【问题描述】:

我正在浏览一个 java 代码库,并认为如果我可以暂时公开所有字段和方法,那么了解该软件的工作原理会容易得多。

访问说明符基本上是程序员while he is coding 应遵循的准则(例如,使用setter 而不是直接赋值以允许setter 执行与该字段相关的一些其他工作)。 运行java程序时是否可以告诉jvm忽略访问限制?

另一种可能性是使用一些 IDE 插件,手动将所有内容的可见性更改为 public

【问题讨论】:

  • 。这是一个糟糕的主意。
  • 为什么在 JVM 中这样做?它主要只在编译时产生影响。
  • 我认为您正在寻找的是您的 IDE 调试器。它使您可以单步执行您的代码并随时查看所有变量的值,无论它们是公共的、受保护的还是私有的。
  • 首先限制可见性的部分原因是它允许您推理需要关心访问受限元素的代码部分。如果某些东西是私有的,你知道你只需要关心它所在的编译单元。将东西公开基本上意味着你必须关心所有代码如何与之交互。简而言之:你会让你的工作变得更加困难。

标签: java testing jvm public


【解决方案1】:

样式指南通常认为这是叛国罪

选项:

  • 你仍然可以使用 java 反射来设置字段(private、final 或其他),但缺点是你不能像 public 一样编码,你仍然需要调用一些方法来设置字段为 bla .
  • 使用 JNI 将 C 代码链接到 java,而 C 并不真正关心 Java 的字段可见性。

编译器插件可能会起作用,但是当大多数程序员知道如何使用时,他们也知道这是一个多么糟糕的主意。当然,我现在很想尝试。




笔记: 我有理由确定 java 的 SecurityManager 会反对你试图公开它的数据。

【讨论】:

    【解决方案2】:

    您要求的内容在多个级别上都不起作用。

    1. 您不能在源代码/编译级别执行此操作。它改变了 Java 语言。而且它也不会取得任何成果。

    2. 您不能在运行时以任何有用的方式执行此操作。您可以使用反射使字段可访问。但是,这是不切实际的,因为:

      • 这必须一次完成一个Field,或者一次一个Class;例如

           Field[] fields = clazz.getDeclaredFields();
           AccessibleObject.setAccessible(fields, true);
        
      • 您需要保留所有如此“处理”的Field 对象,因为将Field 对象设置为可访问不会影响同一字段的其他Field 对象。

      • 只有在修改源代码以使用反射和上述Field 对象来访问字段值时,才能使用此功能。

    3. 如果您想了解代码的工作原理,还有其他更好的方法。

      • 阅读和分析源代码。使用 IDE 来帮助您。
      • 使用调试器。调试器允许您查看变量的状态无论变量的访问权限如何。它适用于参数和局部变量以及字段。
      • 在您的代码中添加一些调试日志或跟踪打印。 (并在完成调查后删除更改。使用版本控制来帮助您撤销更改。)

    @ElliottFrisch 为什么这是个坏主意?

    基本上,因为它对你没有帮助。

    【讨论】:

    • 访问覆盖不需要“一次完成一个字段”。您可以将Field 实例的数组传递给AccessibleObject.setAccessible(theArray, true)。但必须强调的是,这不会改变字段的访问级别,只会改变特定的Field 实例。所以访问必须通过这些Field 实例进行,而不是通过其他代表相同字段的Field 实例......
    • 不知道。固定。
    • 当您执行AccessibleObject.setAccessible(clazz.getDeclaredFields(), true) 时,您将一无所获。如前所述,您必须使用您更改了可访问状态的 Field 实例,因此,Field[] theFieldInstancesToUse = clazz.getDeclaredFields(); AccessibleObject.setAccessible(theFieldInstancesToUse, true); /* use the elements of theFieldInstancesToUse */。对clazz.getDeclaredFields() 的下一次调用将返回不同的实例。原则上,您可以构建任意Field[] 数组并将其传递给该方法,但是,我想我们同意它仍然很复杂……
    • 关键是对每个班级的每个领域都做这件事太复杂了(正如 OP 所要求的那样),而且无论如何这无助于他做他真正想做的事情.
    • 这里完全同意。这很复杂,甚至没有帮助。并且它将在未来的版本中停止工作,因为从 Java 9 开始,它应该仅限于向调用者打开的模块。只有一个宽限期允许调整现有软件。
    【解决方案3】:

    您的要求肯定是可以实现的,但提出了一些问题,即您可能想要或需要这样做的原因。设置访问修饰符几乎总是有原因的。实际上,如果您考虑一下为什么将某些字段和方法公开等,它可能会帮助您更多地了解该软件。

    我最近开始了一项新工作,我必须通过一个大型代码库并尝试了解所有内容的作用。我发现使用 Debugger单步执行 代码并查看程序中每个点的每个字段、变量等的值的最佳方式。所有好的 Java IDES 都有调试器。我使用IntelliJ IDEA,它有一个非常有用的调试器,甚至允许您在程序运行的不同点运行自定义评估语句。

    【讨论】:

    • why you might want or need to do it 我正在研究数据结构的实现,我认为如果我可以查看各个字段并查询它的属性会很有帮助。
    • 在这种情况下,调试器将完全满足您的需求! This page 将有助于学习如何使用 IntelliJ IDEA 调试工具。
    • @saga 如果您真的需要,您可以使用反射访问所有字段。这样您就可以访问它们,而不管它们的访问修饰符如何。
    猜你喜欢
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    相关资源
    最近更新 更多