Java 使用ant重新编译会导致代码在运行时崩溃吗?

Java 使用ant重新编译会导致代码在运行时崩溃吗?,java,ant,compilation,Java,Ant,Compilation,我有一个简单的java项目,我正在使用ant构建它。它有以下两类: A.java: public class A { public static void main(String[] args) { Integer i = 0; B.f(i); } } B.java: public class B { public static void f(int i) { System.out.println("hello");

我有一个简单的java项目,我正在使用ant构建它。它有以下两类:

A.java:

public class A {
    public static void main(String[] args) {
        Integer i = 0;
        B.f(i);
    }
}
B.java:

public class B {
    public static void f(int i) {
        System.out.println("hello");
    }
}
哪种方法很好:

$ ant compile
[...]
$ java -cp bin A
hello
现在,如果我将
B.f
中的
int
参数更改为
对象

public class B {
    public static void f(Object i) {
        System.out.println("hello");
    }
}
…代码重新编译得很好

$ ant compile
[...]
$ java -cp bin A
Exception in thread "main" java.lang.NoSuchMethodError: B.f(I)V
    at A.main(Unknown Source)
。。。但它在运行时崩溃。为什么?


编译前的文件夹结构:

bin
build.xml
src
├── A.java
└── B.java
build.xml:

<project>
    <target name="compile">
        <javac srcdir="src" destdir="bin"/>
    </target>
</project>

Ant将只编译自上次编译以来未更改的文件(除非清除)。也就是说,只有一个文件发生了更改,而另一个文件正在打电话,希望使用旧版本。如果在运行ant构建之前删除所有类文件,我敢打赌它一定会工作

在ant任务的apache文档中指出:

将递归扫描源目录和目标目录以查找 要编译的Java源文件。只有没有 对应的.class文件或类文件比 .java文件将被编译

这些方法可能在源代码级别兼容,但当编译成字节码时,它们具有其他类正在寻找的特定签名。您更改了已编译签名,因此它找不到正在查找的方法

------------编辑------------------

可以将简单的清理任务添加到构建中:

  <target name="clean"
        description="clean up" >
    <!-- Delete the ${build} and ${dist} directory trees -->
    <delete dir="${build}"/>
    <delete dir="${dist}"/>
  </target>

您可以添加一个完整的重建:

  <target name="fullReBuild" depends="clean compile">
  </target>


然后根据需要从命令行发出
ant fullReBuild

默认情况下,除非文件日期更改,否则ant不会重新编译任何内容。解决方法是使用任务。这使得ant在依赖项发生变化时重新编译依赖项。

这听起来相当可疑。这意味着ant的重新编译策略几乎是无用的,每次编译时,您也可以删除所有的类。然而,
A
不应该仍然使用新的
B
,因为参数是兼容的吗?@Dog,我可能错了,但是你是否尝试删除类文件并运行ant构建?从你评论中的链接来看,似乎必须使用
任务才能使重新编译正常工作。@Dog,这取决于你所说的正常工作。Ant不会重新编译未更改的内容,以便在大型项目上快速构建。大多数人为“clean”创建另一个目标,并在需要完全重建时在
ant
之前使用
ant clean
。请参阅上面的我的编辑。您知道
?它似乎解决了已更改类的依赖项的传递闭包问题,然后重新编译它们,因此就我所见,应该可以很好地工作。它解决了我的问题。如果我创建了一个
clean
目标(我已经有了),我如何知道何时使用
clean
而不是重新编译?这个问题刚刚发生在我身上,我花了两个小时才找到,因为事情在随机的时间之后就崩溃了。当我进行此更改时,我怎么知道我应该使用
clean