java Generics通配符

8 java generics type-systems

我对Java的泛型类型中使用通配符有疑问:List<? extends Set>和之间的基本区别是List<T extends Set>什么?我什么时候使用?

blu*_*ubb 8

两个原因:

为了避免不必要的演员:

你必须使用这种T情况的变体:

public <T extends Set> T firstOf(List<T> l) {
    return l.get(0);
}
Run Code Online (Sandbox Code Playgroud)

随着?这将成为:

public Set firstOf2(List<? extends Set> l) {
    return l.get(0);
}
Run Code Online (Sandbox Code Playgroud)

...它不向该firstOf方法的调用者提供相同数量的信息.第一个版本允许调用者执行此操作:

SubSet first = firstOf(listOfSubSet);
Run Code Online (Sandbox Code Playgroud)

而对于第二个版本,您被迫使用强制转换来进行编译:

SubSet first = (SubSet)firstOf(listOfSubSet);
Run Code Online (Sandbox Code Playgroud)

要强制匹配参数类型:

public <T extends Set> boolean compareSets(List<T> a, List<T> b) {
    boolean same = true;
    for(T at : a) {
        for (T bt: b) {
             same &= at.equals(bt);
        }
    }
    return same;
}
Run Code Online (Sandbox Code Playgroud)

没有直接等效使用?而不是T为此.需要注意的是,由于Java的单调度,在上面的版本,编译器会调用atequals(T)方法,这很可能不同于atS' equals(Set)equals(Object)方法.


Col*_*inD 1

这里的区别在于,在第二个版本中,您有一个类型变量,它T引用包含的特定子类型。当您需要确保其他内容与列表中包含的类型类型相同时,您需要这样做。几个简单的例子:SetList

// want to ensure that the method returns the same type contained in the list
public <T extends Set> T something(List<T> list) {
  ...
}

// want to ensure both lists contain the exact same type
public <T extends Set> List<T> somethingElse(List<T> first, List<T> second) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

简单规则:T extends Foo如果两个地方需要相同的类型,请在方法签名中使用类型变量。方法参数各在一个地方,方法返回类型在另一处。? extends Foo如果您只需要确保在一个地方处理“某种东西”,请使用通配符Foo

另外:不要使用原始类型Set