Javac成功地重新编译了我的所有类,除了一个我叫做“Box.java”的类。如果特别要求,Javac会编译它:javac Box.java
,但不能作为整个项目重新编译的一部分。
我是否正确地认为这是因为事实证明,有一个名为“Box”的类(Swing的一部分我相信,我一般在其他地方使用Swing)?通过重命名我的类(以及相关的方法等)“DecisionBox.java”,问题似乎消失了。
如果这是对的,那么将来避免的最佳方法是什么。我可以很容易地找到一个Java保留字列表,但保留类....?只搜索JavaDocs?或者IDE会发现此错误吗?
我只是问,因为没有错误消息需要很长时间才能找到一个类没有被重新编译...
答案 0 :(得分:2)
这取决于你如何编译整个项目,以及你的其他源文件如何使用Box。
Java编译器将自动编译依赖项。您有一个名为Box
的类与javax.swing.Box
同名,这不是问题,因为包名称用于区分。
但是,例如,您编译的其他类都不是指您的 Box
。例如,如果您在任何地方import javax.swing.*
,然后只使用Box
,则该类很可能正在使用javax.swing.Box
。如果编译器始终可以将Box
解析为javax.swing.Box
,则没有理由编译Box
,因为就其而言,您永远不会使用它。
如果您使用源文件的默认包(即没有包),这可能会引发更多混淆。您希望保持井井有条,并尽可能明确地了解包。使用默认包意味着您无法明确限定自己类的名称。
确保您确保从包中导入特定类而不是javax.swing.*
,并且如果您需要在同一源文件中同时使用Box
和javax.swing.Box
,请明确指定包名称。
换句话说,听起来好像编译器在某些时候没有看到你的 Box
是你的类正在使用的那个 - 以及显式导入和完全使用合格的包名可以消除这种混淆。
您可以尝试的一个实验是删除所有已编译的.class
文件,然后重新编译您的项目。如果永远不会编译Box.java
,那么即使您认为自己可以使用它,也可能不会使用它。
基本上,如果有的话,这是不使用通配符包导入的好例子。通过始终显式导入您正在使用的类,您可以显着降低编译器对您的意图做出错误假设的机会。这(以及在较小程度上,不使用默认包)是避免将来出现这种情况的最佳方法。
根据评论中的新信息进行更新:OP有一个关系图,如:
FirstClass
Topic
Boat
DecisionBox
Boat
/ DecisionBox
在修改后不会重新编译的原因是Topic
没有改变。因此,当您重新编译FirstClass
时,它会检查Topic
。 Topic
不需要重新编译,因此不会检查Topic
的依赖项。如果FirstClass
直接引用Boat
(即使例如Topic.getBoat()
),则会重新编译Boat
。这是javac
非常基本的依赖性行走的缺点。在重新编译之前删除所有.class,或者你可以使用其他一些构建系统,比如ant(你可以指定依赖项)或IDE的内部系统(例如,大多数IDE会为你神奇地处理这个问题,尽管学习当然很好命令行界面,实际上很少在没有补充构建系统的情况下使用它。)
<小时/> 顺便说一句,另一种可能性,虽然这种可能性要小得多,但是
Box.java
或编译Box.class
上的一些不正确的时间戳会导致编译器认为它没有改变,因此不需要重新编译。如果.java
文件上的时间戳比.class
文件新,或者.class
不存在,则只会重新编译该文件。