7

我正在尝试确定是否需要在我们的构建链中重新编译一些 jar,例如,如果我有以下结构,jar 1 在其源更改时编译,jar 2 在其源更改或 jar 1 重新编译时编译.

罐子 1:

public class Foo /* impl*/

罐子 2:

public class Bar extends Foo /*impl*/

假设两个班级之间的合同没有改变,即。添加抽象方法或将方法添加到接口等。

我需要重新编译 jar 2 吗?IE。如果对 Foo 中的私有方法进行了一些更改,是否需要重新编译 Bar?

我尝试通过在更改一堆后比较两个类的字节码来测试这一点,并且正如预期的那样它没有改变。然而,我的同事坚持认为,他们遇到过这样的情况,即使合同没有改变,他们也必须重新编译所有内容才能使其工作,但是他们不记得原因是什么......所以举证责任在我身上证明那不应该是必要的。是否存在对超类进行更改需要重新编译子类的情况,即使两者之间的接口保持不变?

4

3 回答 3

6

假设Foo是由一个开源组织发布的;并且有数以千计的Foo不同公司实施的子类。

现在,如果对Foo. 当然不是。(好吧,我们确实一直在重新编译所有代码,但这不是必需的——新的 jarFoo可以简单地放入而不会造成任何问题)

这是二进制兼容性的问题,您可以检查规范以确保更改Foo为安全。请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html

于 2013-02-26T19:04:40.630 回答
3

在一般情况下,您必须重新编译依赖类。但是,如果您没有更改Foo所使用的任何方法或字段,则在更改时Bar不必重新编译。BarFoo

例如,如果调用Foo了方法,但您将其签名更改为或将其可见性更改为您必须重新编译。在这种情况下无法编译:您必须更改其代码。protected int foo()Barprotected String foo()privateBarBar

但是,如果Bar不使用方法foo()或仅更改了实现细节,则无需重新编译foo()即可使用。Bar

于 2013-02-26T19:02:48.103 回答
2

绝对不会。您可以使用打包在 jar 文件中的框架(包含许多具有类似 Foo 的合同的类),而无需从源代码编译它们。但是您需要绝对确定合同没有直接间接更改。一些间接变化的例子:

public class Foo { //v1
    public static final int CONSTANT = 1;         
}

public class Foo { //v2
    public static final int CONSTANT = 2;         
}

public class Bar extends Foo {
    private int a(int value) {
        switch (value) {
            case CONSTANT:
                return 1;
        }
        return 2;
    }
}

如果您不重新编译类 Bar,它仍将使用值 1。

于 2013-02-26T19:04:36.393 回答