2011-06-21 78 views
4

我有一个Java项目,涉及类GUIConstants - 各种public static final参数用于布局图形用户界面,因为不同的组件有时必须是相同的大小或颜色或任何。蚂蚁不重新编译常量

我目前正在做一个可视化重新设计的阶段,其中涉及改变这些常数中的一些。然而,ant正在使这一难题。我将更改参数并重新编译,但仍旧使用旧值。如果我为其中一个使用它并重新编译的文件添加一些微不足道的修改,将会使用正确的值。但是它很烦人,而且很容易出错,不得不查找所有文件并修改它们。当然有一种方法可以强制ant重新编译未更改的文件......我只是无法在手册页中找到它。我的假设是,当编译一个使用final变量的类时,Java改为使用该值本身,而不是对该变量指向的任何引用(类似于对常量使用#DEFINE的方式在C中工作)。所以即使变量指向别的东西,原始值也会被烘焙到.class文件中。这是真的? (它不影响我的问题,我只是好奇。)

在此先感谢。

+0

不能相信没有真正的解决方案。对每个构建使用清理是几个常量的一个很好的解决方案。 – Stiefel

回答

2

你的假设几乎是正确的。这不仅仅是final变量,虽然,但所谓的“constant variables”:

我们把一个变量,基本类型或输入字符串,这是最终的和有一个编译时间常数表达式(§15.28)常数变量初始化。变量是否为常量变量可能对类初始化(§12.4.1),二进制兼容性(§13.1,§13.4.9)和明确赋值(§16)有影响。

然后,在上binary compatibility (§13.1)的部分:

引用是恒定变量(§4.12.4)在编译时被解析为表示的恒定值的字段。没有提到这种恒定字段应该是存在于一个二进制文件中的代码(除类或含有该常量字段,这将有代码以初始化它接口)

和(§13.4.9)(我的重点):

如果字段是一个常量变量(§4.12.4),则删除该关键字最终或改变其值不会通过使它们不运行中断与预先存在的二进制兼容性,但除非重新编译,否则他们将不会看到该字段使用的任何新值。

在之前的工作中,我们利用这种方法建立了一种条件编译系统,这样我们就可以生成带有所有调试语句的生产二进制文件。

当你把这个随路javac task决定了类重新编译你得到你所看到的行为:

没有相应的.class文件或

只有Java文件在类文件是比老.java文件将被编译。

注意:Apache Ant仅使用源文件和类文件的名称来查找需要重建的类。它不会扫描源代码,因此不会了解有关嵌套类,与源文件名称不同的类,等等。除了存在/修改时间以外,请参阅<depend>任务以进行依赖性检查。

解决这一问题将是,每次做一个干净的完整的编译,喜欢的东西ant clean compile最简单的方法(假设你有一个clean目标,消除所有的类文件)。尽管这可能太慢了。

我也打算建议您看depend任务,正如javac任务的文档中所建议的那样,但是查看文档(我自己并没有真正使用它),似乎它赢了(请参阅“限制”一节):

这些限制最明显的例子是,当其他类导出的常量原始数据类型发生更改时,任务无法确定要重新编译哪些类。

一个可能的解决方法,如果你发现每过慢的时间做一个干净的编译,将是使你的GUIConstants类中的值不会常量,至少你的同时进行更改。您可以通过评论所有final关键字来使这些值不是最终的,然后其他类应该会看到您的更改。当你对新值感到满意时,把final放回原处并重新编译(并测试当然一切仍然正常)。

+0

final对这个问题没有影响 –

1

您想要使用clean任务删除dist目录中的所有文件。或者你正在放置二进制文件的地方。

2

你的理论是错误的。 Java将决赛嵌入到周围类文件的常量池中,就像它执行任何非决赛一样。没有特殊的“最终”优化,只有一个标志表明它只能在施工过程中设置。

在构建链中出现某种错误的可能性要好得多,比如从旧源“更新”的类或一组类,或从尚未更新的类“构建”的jar文件,或引用以前版本的jar文件的程序等。验证这一点的一种快速方法是删除所有编译的项目。通常这是通过ant build.xml文件中的“干净”目标完成的;然而,这个目标也可能是手写的,所以不要认为它总是正确的(特别是如果你增加额外的中间构建步骤,如类增强等)。

0

“理论”似乎都不正确,清除静态没有效果,重新编译清理总是有效,我的构建“系统”几乎只依赖于子目录中的源代码,而没有其他外部的罐子,所以没有“陈旧“的课程挂在

在我的情况下,我不得不做一个完整的重建我的来源的一个领域 - 我直接包括一个来源的库,不需要重新编译,但包括一个单独的” deepclean“的规则,但是与这个问题隔离...

+0

澄清虽然它没有回答这个问题,但它重要地表明,其他两个答案也不......为什么在这两个问题上添加完全相同的评论,这将是pedantry。 –

0

DJClayworth在这个answer的答案建议使用类似以下的构造来愚弄编译器:

public static final int INT_VALUE = Integer.valueOf(100).intValue(); 

它使编译器看不到此成员的常量字符。我只是测试它,它的工作原理。在将常量改为上述构造之后,不要忘记执行一次完整的清理。

不是一个美丽的解决方案,但对于暂时的解决方法很有帮助。