Java Generics:特殊用法<t extends =“”object =“”&=“”interface =“”>

时间:2015-09-26 10:09:09

标签: java generics

我经常在Java中找到使用泛型的代码:

public static <T extends Object & Interface> foo(T object) {
    ...
}

因为在Java中,每个类都继承自对象类,所以我不确定extends Object是否具有特殊含义或用于特殊目的。任何人都可以告诉我,如果有不同的背景使用这个或者这是隐含的,当你采取<T extends Interface>

3 个答案:

答案 0 :(得分:5)

<T extends Object & Interface>

Object显然是多余的,通常等于

<T extends Interface>

请注意,强烈建议不要使用Interface作为班级名称。

答案 1 :(得分:0)

正如您所指出的,任何T都会隐式地延伸Object。明确定义T extends Object是完全多余的,您可以(也可能应该)将其删除,只需定义T extends Interface

答案 2 :(得分:0)

可能是使您的代码在二进制级别向后兼容所必需的。假设您有以下实用程序类:

public class Utils {
    public static <T> int length(T obj) {
        if(obj instanceof CharSequence) {
            return ((CharSequence)obj).length();
        }
        return 0;
    }
}

它作为库发布,并在某些应用程序中使用:

public class Main {
    public static void main(String... args) {
        System.out.println(Utils.length("foo"));
    }
}

工作正常。但是后来你决定将方法仅限于某些接口CharSequence的实现是好的,因为对于其他对象,它总是返回0并且似乎没有人使用你的方法和非CharSequence参数。所以你将签名改为

public static <T extends CharSequence> int length(T obj) { ... }

现在,如果您将Main课程与图书馆的新版本相关联,则会因java.lang.NoSuchMethodError而失败。那是因为你方法的擦除签名发生了变化。在int length(Object obj)之前,但现在是int length(CharSequence obj)。如果重新编译Main类,它将正常工作,但并不总是可以重新编译所有现有代码。因此可以执行诀窍:

public static <T extends Object & CharSequence> int length(T obj) { ... }

现在你实际上是将参数限制为CharSequence界面,但删除的签名又回到int length(Object obj)(删除的类型始终是A & B & C & ...链中的第一个,它是正式记录),因此新版本的Utils类与旧代码二进制兼容。