有没有办法在编译时为Java定义一个常量值

2022-09-04 06:37:05

当我曾经用C / C++编写库时,我养成了一个返回编译日期/时间的方法的习惯。这总是编译到库中,因此可以区分库的构建。我通过在代码中返回#define得到了这个:

C++:

#ifdef _BuildDateTime_
   char* SomeClass::getBuildDateTime() {
      return _BuildDateTime_;
   }
#else
   char* SomeClass::getBuildDateTime() {
      return "Undefined";
   }
#endif

然后在编译时,我在构建脚本中有一个'-D_BuildDateTime_='。Date

有没有办法在Java中实现这一点或类似目标,而无需记住手动编辑任何文件或分发任何单独的文件。

我从一位同事那里得到的一个建议是获取 ant 文件以在类路径上创建一个文件,并将其打包到 JAR 中,并由该方法读取它。

类似的东西(假设创建的文件被称为“DateTime.dat”):

// I know Exceptions and proper open/closing 
// of the file are not done. This is just 
// to explain the point!
String getBuildDateTime() {
    return new BufferedReader(getClass()
            .getResourceAsStream("DateTime.dat")).readLine();
}

在我看来,这是一个黑客攻击,可以被在JAR外部具有类似名称文件的人规避/破坏,但是在类路径上。

无论如何,我的问题是是否有任何方法可以在编译时将常量注入到类中。

编辑

我之所以考虑在JAR中使用外部生成的文件,是因为这是一个库,将嵌入到客户端应用程序中。这些客户端应用程序可以定义自己的类装入器,这意味着我不能依赖标准的JVM类装入规则。

我个人倾向于按照serg10的建议使用JAR文件中的日期。


答案 1

我赞成基于标准的方法。将您的版本信息(以及其他有用的发布者信息,例如内部版本号,Subversion修订号,作者,公司详细信息等)放在jar的清单文件中

这是一个有据可查且易于理解的 Java 规范。对于创建清单文件(例如核心Ant任务maven jar插件),存在强大的工具支持。这些可以帮助自动设置一些属性 - 我已经配置了maven,以便在构建时将jar的maven版本号,Subversion修订版和时间戳放入清单中。

您可以使用标准的java api调用在运行时读取清单的内容 - 如下所示:

import java.util.jar.*;

...

JarFile myJar = new JarFile("nameOfJar.jar");    // various constructors available
Manifest manifest = myJar.getManifest();
Map<String,Attributes> manifestContents = manifest.getAttributes();

对我来说,这感觉像是一种更Java标准的方法,所以对于后续的代码维护者来说,可能更容易理解。


答案 2

我记得在一个开源项目中看到类似的东西:

class Version... {
  public static String tstamp() {
    return "@BUILDTIME@";
  }
}

在模板文件中。使用 Ant 的过滤副本,您可以为此宏指定一个值:

<copy src="templatefile" dst="Version.java" filtering="true">
    <filter token="BUILDTIME" value="${build.tstamp}" />
</copy>

在编译步骤之前,使用此选项在生成过程中创建版本.java源文件。


推荐