Java 如果父类/接口发生更改,类的字节码是否会更改?
我试图确定是否需要重新编译构建链中的一些jar,例如,如果我有以下结构,JAR1在其“源”更改时编译,JAR2在其“源”更改时编译,或者JAR1重新编译时编译 jar 1:Java 如果父类/接口发生更改,类的字节码是否会更改?,java,class,bytecode,Java,Class,Bytecode,我试图确定是否需要重新编译构建链中的一些jar,例如,如果我有以下结构,JAR1在其“源”更改时编译,JAR2在其“源”更改时编译,或者JAR1重新编译时编译 jar 1: public class Foo /* impl*/ jar 2: public class Bar extends Foo /*impl*/ 假设两个类之间的契约不变,即添加抽象方法或向接口添加方法等 我需要重新编译jar2吗?例如,如果对Foo中的私有方法进行了一些更改,Bar是否需要重新编译 我试图通过比较两个类的
public class Foo /* impl*/
jar 2:
public class Bar extends Foo /*impl*/
假设两个类之间的契约不变,即添加抽象方法或向接口添加方法等
我需要重新编译jar2吗?例如,如果对Foo中的私有方法进行了一些更改,Bar是否需要重新编译
我试图通过比较两个类的字节码来测试这一点,在一个类中更改了一组字节码之后,正如预期的那样,它没有更改。然而,我的同事坚持说,他们遇到过这样的情况:即使合同没有更改,他们也必须重新编译所有内容才能正常工作,但他们不记得原因是什么。。。因此,我有责任证明这是不必要的是否存在这样一种情况,即即使两个子类之间的接口保持不变,对超类进行更改也需要重新编译子类?在一般情况下,您必须重新编译依赖类。但是,如果您没有更改
Foo
的Bar
使用的Foo
的任何方法或字段,则在Foo
发生更改时,您不必重新编译Bar
例如,如果Foo
有方法protectedintfoo()
被Bar
调用,但您将其签名更改为protectedstringfoo()
或将其可见性更改为private
,则必须重新编译Bar
。在这种情况下,Bar
无法编译:您必须更改其代码
但是,如果
Bar
不使用方法foo()
,或者如果只更改了foo()
的实现细节,您可以使用Bar
,而无需重新编译。当然不可以。您可以使用框架(其中包含许多具有类似foo的契约的类)它打包在jar文件中,您不需要从源代码处编译它们。但你们需要绝对确保合同并没有直接或间接地改变。一些间接变化的例子:
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;
}
}
如果不重新编译类栏,它仍将使用值1 比如说
Foo
是由一个开源组织发布的;各种公司实现了数千个子类的Foo
现在,如果对Foo
进行了一些更改,并且以二进制形式发布了新版本,那么所有公司都应该重新编译代码吗?当然不是。(好吧,我们一直都在重新编译所有代码,但这不是必需的-只需插入Foo
的新jar,就不会引起任何问题)
这是二进制兼容性的问题,您可以检查规范以确保对
Foo
的更改是安全的。请参见更改Bar使用的Foo中的常量值也需要重新编译。此外,java有定义良好的规则。方法重载也存在潜在问题。显然,如果添加了重载方法,则在不重新编译的情况下将无法使用它。这是否意味着Bar.class文件将在其中包含常量
int的值?我的直觉是,它只引用了Foo/CONSTANT
,并将在运行时相应地更新。你知道为什么不是这样吗?如果你用的不是开关,可能是的。Switch指令需要显式的数字,而compile无法在运行时从常量字段读取值。感谢链接,我想我希望只要源代码没有更改,类文件就永远不需要更改。哦,好吧。