我经常在Java中找到使用泛型的代码,如下所示:
public static <T extends Object & Interface> foo(T object) {
...
}
Run Code Online (Sandbox Code Playgroud)
因为在Java中,每个类都继承自对象类,所以我不确定它是否extends Object具有特殊含义或用于特殊目的.任何人都可以告诉我,如果有不同的背景使用这个或者这是隐含的,当你采取<T extends Interface>?
<T extends Object & Interface>
Run Code Online (Sandbox Code Playgroud)
这Object显然是多余的,通常等于
<T extends Interface>
Run Code Online (Sandbox Code Playgroud)
请注意,Interface强烈建议不要使用作为类名.
这可能是使您的代码在二进制级别向后兼容所必需的。假设您有以下实用程序类:
public class Utils {
public static <T> int length(T obj) {
if(obj instanceof CharSequence) {
return ((CharSequence)obj).length();
}
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
它作为库发布并在某些应用程序中使用,如下所示:
public class Main {
public static void main(String... args) {
System.out.println(Utils.length("foo"));
}
}
Run Code Online (Sandbox Code Playgroud)
工作正常。然而后来您决定将您的方法限制为仅实现某些接口,CharSequence因为对于其他对象它总是返回 0 ,并且似乎没有人将您的方法与非 CharSequence 参数一起使用。所以你将签名更改为
public static <T extends CharSequence> int length(T obj) { ... }
Run Code Online (Sandbox Code Playgroud)
现在,如果您将该Main类与新版本的库链接,它将失败并显示java.lang.NoSuchMethodError. 那是因为你的方法的擦除签名发生了变化。以前是int length(Object obj),但现在是int length(CharSequence obj)。如果重新编译该类Main,它将正常工作,但并不总是可以重新编译所有现有代码。因此可以执行这个技巧:
public static <T extends Object & CharSequence> int length(T obj) { ... }
Run Code Online (Sandbox Code Playgroud)
现在您实际上将参数限制为CharSequence接口,但擦除的签名又回到了int length(Object obj)(擦除的类型始终是 链中的第一个A & B & C & ...,这是官方记录的),因此新版本的Utils类与旧代码是二进制兼容的。