【问题标题】:How can I access a java compile time parameter at runtime?如何在运行时访问 java 编译时参数?
【发布时间】:2017-02-15 18:48:32
【问题描述】:

我们正在将用 C 编写的系统迁移到 Java,并且必须保留现有流程(没有争议)。我们目前使用 C 预处理器将编译时信息“嵌入”到 C 应用程序中,例如:

cc -o xxx.o -DCOMP_ARG='"compile time arg"' xxx.c

xxx.c 文件然后可以使用“COMP_ARG”,它的值将嵌入到代码中,我们不必担心它会被无意更改。

我们意识到 Java 喜欢使用属性文件,但是,我们的要求是在代码中嵌入一些信息 ** **,因此属性文件不是一个选项 - 这些特定值不能在运行时指定。为了说明这一点,这些数据可能是文件编译时间的时间戳,但确切的数据与问题无关。

我们正在寻找一种在编译时指定 Java 代码可用的各种值的方法。我们很清楚 Java 没有 C 的预处理器,所以机制会有所不同。

我们当前的解决方案是使用代码生成步骤 (Maven),它确实有效,但是 Eclipse 试图处理源文件造成了严重破坏,因此我们关闭了“自动构建”。我们真的很想找到一个更强大的解决方案。

感谢您的帮助,谢谢。

【问题讨论】:

  • properties maven 处理属性?您所说的“Eclipse 试图处理源文件正在造成严重破坏”是什么意思?您可以发布您生成的文件的示例吗?
  • Eclipse 问题与我们想摆脱通过 Maven 过滤器运行模板文件的另一个原因无关——该解决方案将我们锁定在 Maven 中。
  • RC - 感谢您的链接。您建议的问题与从属性文件生成源文件有关。这几乎就是我们现在正在做的——使用一个在脚本中定义了“属性”的 Maven 过滤器——该脚本负责收集值并将它们提供给编译器(当前是 C)——你建议的方法会让我们创建一个额外的步骤,这都不是我们的目标。
  • 锁定到 maven 确实让我发笑。

标签: java


【解决方案1】:

xxx.c 文件然后可以使用“COMP_ARG”并且它的值将被嵌入 在代码中,我们几乎不用担心它会被更改 不经意间。

...我们的要求是将一些信息嵌入到 代码……

我们正在寻找一种在编译时指定各种值的方法 可用于 Java 代码。我们很清楚 Java 确实 没有像 C 那样的预处理器,所以机制是 不同。

似乎解决此问题的最佳方法是在您的代码中使用注解

在 Java 中,注解是一种接口声明,但它们并不强制执行与实现类的行为契约。相反,它们旨在定义与某些外部框架、预处理器或编译器本身的契约。注释在 Java EE 5.0(及更高版本)中广泛使用,以指定开发人员代码在其中运行的框架的配置和行为。 JavaDoc 文档处理器也广泛使用注释。在这里,doc cmets 中的注释允许您指定和格式化您打算在 JavaDoc 处理器运行时出现在文档中的信息。

注释可以定义为在运行时可访问。在这种情况下,访问注解的主要机制是 Java 反射工具。例如,保留策略为RUNTIME 并在类上定义的注释可以通过该类对应的Class 对象访问:

Class myCls = MyClass.class;   // the "class literal" for MyClass
Annotation[] annotations = myCls.getDeclaredAnnotations();

注解可以包含参数的参数,以提供更大的配置灵活性。当代码本身可以这样注释时,使用注释是最方便的。

有关如何在 Java 中定义和使用注解的快速教程可在此处获得:https://docs.oracle.com/javase/tutorial/java/annotations/

【讨论】:

  • scottb - 感谢您的回复 - 我可以看到如何使用运行时注释来获取数据,但是如何在编译时提供数据值?
  • 您的问题提到在代码中嵌入数据是一项要求。我明白这不是你的目标吗?我不知道将信息动态编译到您的代码中的公认且特征良好的机制...... Java 是一种强静态类型的语言,不适合此目的。当然,可以通过 XML 甚至命令行在运行时向 Java 程序提供数据,但我怀疑这不是您要问的。此类数据不会成为您编译程序的一部分。
  • 我松散地使用术语“数据”。我最好的例子是'private static final String compilationTime = "xxxxxx";'其中 x 将被进程替换或通过构造函数传递给最终变量。与 XML 和属性有关的问题是那些由文件提供的,并且文件可能与应用程序不匹配。我们有 C 的过程,正如许多人指出的那样,使用 Java 是痛苦的。我在 Maven 过滤方面取得了一定程度的成功,但正在寻找更好的解决方案。
  • 我知道这不受支持,但如果我能做到这一点:'javac -J-Dname-value ...' 这样 javac 添加代码来定义“name=value”就好像它是在java命令行上,就可以了。我们可以在运行时指定很多东西,但有些东西需要加入。
  • 对于这种情况,另一种方法是定义一个枚举类来包含您指定给 C 预处理器的数据。然而,枚举类被编译到您的程序中,并且只能通过编辑类并重新编译程序来更改。如果您的枚举类被命名为PreprocessorData,那么您将在您的应用程序中将此数据用作String myString = PreprocessorData.EnumConstantForThisDirective.getValue(); ...再次,Java 被设计为安全且强类型,因此它不是为执行您在 C 中所做的事情而设计的。你将不得不以某种方式解决问题。
【解决方案2】:

我将发布我自己的答案,似乎是“无法完成” - 显然,无法在编译时向 Java 提供一组参数,这些参数将传递给程序在执行时。解决方案似乎是继续我正在做的事情,即使用编译时数据更新 Java 源文件,并弄清楚如何哄 Eclipse 停止覆盖文件。

感谢所有评论的人。

【讨论】:

    猜你喜欢
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    • 2012-12-14
    相关资源
    最近更新 更多