gpt4 book ai didi

java - 使具有相同删除二进制文件的通用返回类型兼容吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:29:37 25 4
gpt4 key购买 nike

我有以下类(class):

public abstract Foo {
Foo() {}

public abstract Foo doSomething();

public static Foo create() {
return new SomePrivateSubclassOfFoo();
}
}

我想把它改成下面的定义:

public abstract Foo<T extends Foo<T>> {
Foo() {}

public abstract T doSomething();

public static Foo<?> create() {
return new SomePrivateSubclassOfFoo();
}
}

此更改二进制兼容吗?即,针对类的旧版本编译的代码是否可以在不重新编译的情况下与新版本一起使用?

我知道我需要更改 SomePrivateSubclassOfFoo,没关系。我也知道这个更改会在编译旧客户端代码时触发有关原始类型的警告,这对我来说也可以。我只是想确保不需要重新编译旧的客户端代码。

根据我的理解,这应该没问题,因为 T 的删除是 Foo,因此字节码中的 doSomething 的签名和以前一样。如果我查看 javap -s 打印的内部类型签名,我确实看到了这一点(尽管没有 -s 打印的“非内部”类型签名确实不同) .我也确实对此进行了测试,它对我有用。

然而,Java API Compliance Checker告诉我这两个版本不是二进制兼容的。

那么什么是正确的呢? JLS 是否保证这里的二进制兼容性,或者我只是在测试中走运? (为什么会这样?)

最佳答案

是的,您的代码似乎没有破坏二进制兼容性。
我在爬取/阅读后发现了这些
http://docs.oracle.com/javase/specs/jls/se8/html/jls-13.html#jls-13.4.5上面写着:-

Adding or removing a type parameter of a class does not, in itself, have any implications for binary compatibility.
...
Changing the first bound of a type parameter of a class may change the erasure (§4.6) of any member that uses that type parameter in its own type, and this may affect binary compatibility. The change of such a bound is analogous to the change of the first bound of a type parameter of a method or constructor (§13.4.13).

还有这个http://wiki.eclipse.org/Evolving_Java-based_APIs_2#Turning_non-generic_types_and_methods_into_generic_ones进一步阐明:-

According to the special compatibility story, the Java compiler treats a raw type as a reference to the type's erasure. An existing type can be evolved into a generic type by adding type parameters to the type declaration and judiciously introducing uses of the type variables into the signatures of its existing methods and fields. As long as the erasure looks like the corresponding declaration prior to generification, the change is binary compatible with existing code.

所以你现在没有问题,因为这是你第一次生成那个类。

但请记住,因为上面的文档也说:-

But, also bear in mind that there are severe constraints on how a type or method that already is generic can be compatibly evolved with respect to its type parameters (see the tables above). So if you plan to generify an API, remember that you only get one chance (release), to get it right. In particular, if you change a type in an API signature from the raw type "List" to "List<?>" or "List<Object>", you will be locked into that decision. The moral is that generifying an existing API is something that should be considered from the perspective of the API as a whole rather than piecemeal on a method-by-method or class-by-class basis.

所以我觉得,第一次做这个改变是可以的,但你只有一次机会,所以要充分利用它!

关于java - 使具有相同删除二进制文件的通用返回类型兼容吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42174045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com