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

当我以前用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文件中的日期。

我赞成基于标准的方法。 将您的版本信息(以及其他有用的发布者内容,如内部版本号,颠覆版本号,作者,公司详细信息等)放入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 manifestContents = manifest.getAttributes(); 

对我而言,这感觉就像是一种更加Java标准的方法,因此后续代码维护者可能会更容易理解。

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

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

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

    

在编译步骤之前,使用它在构建过程中创建Version.java源文件。

AFAIK没有办法用javac做到这一点。 这可以通过Ant轻松完成 – 我将创建一个名为BuildTimestamp.java的第一个类对象,并在编译时通过Ant目标生成该文件。

这是一个有用的Ant类型 。

除非您想通过C / C ++预处理器(这是一个很大的NO-NO)运行Java源代码,否则请使用jar方法。 还有其他方法可以从jar中获取正确的资源,以确保有人没有在类路径上放置重复的资源。 你也可以考虑使用Jar清单。 我的项目使用清单完成您正在尝试做的事情(使用构建日期,修订版,作者等)。

你会想要用这个:

 Enumeration resources = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF"); 

这将获得类路径上的所有清单。 您可以通过解析URL来确定他们可以从哪个jar中获取。

我个人会在你的jar中找到一个单独的属性文件,你在运行时加载…类加载器有一个定义的搜索文件的顺序 – 我不记得它是如何完全在手边工作,但我不知道认为类路径上某处具有相同名称的另一个文件可能会导致问题。

但另一种方法是在编译它们之前使用Ant将.java文件复制到另一个目录中,并在适当的情况下过滤String常量。 你可以使用类似的东西:

 public String getBuildDateTime() { return "@BUILD_DATE_TIME@"; } 

并在Ant文件中编写一个filter,用构建属性替换它。

或许更加Java风格的方式来指示您的库的版本将是向JAR的清单添加版本号,如清单文档中所述 。

我从同事那里获得的一个建议是获取ant文件在类路径上创建一个文件并将其打包到JAR中并让它通过该方法读取。 …在我看来,这是一个黑客,并且可以被在JAR之外具有类似命名文件的人绕开/打破,但是在类路径上。

我不确定让Ant生成一个文件是一个非常令人震惊的黑客,如果它是一个黑客。 为什么不生成属性文件并使用java.util.Properties来处理它?