Collections.max签名的说明
当我偶然发现这个方法签名时,我正在阅读一篇关于Java Generics的文章:
static <T extends Object & Comparable> T max(Collection coll);
我没有得到的部分是我们需要的原因
Collection coll
不会
Collection coll
做得好吗?
有人可以解释为什么下面的签名不合适吗?
static <T extends Object & Comparable> T max(Collection coll);
提前感谢您的回复。 这让我困惑了很长一段时间..
Gábor是对的。 通配符允许返回对象的静态类型与您输入的集合的声明参数类型不同。 例如,给定这些类:
interface S extends Comparable {} class A implements S { @Override public int compareTo(final @NotNull S o) { return 0; } } class B implements S { @Override public int compareTo(final @NotNull S o) { return 0; } }
而这堂课:
class Test { @Nullable static > T extendsMax( Collection extends T> coll) { return null; } @Nullable static > T max(Collection coll) { return null; } }
观察什么调用编译和什么调用不:
public static void main(String[] args) { final Collection sColl = new ArrayList<>(); final Collection aColl = new ArrayList<>(); final Collection bColl = new ArrayList<>(); final S s1 = Test. extendsMax(sColl); // compiles, T = S, extends T> = S final S s2 = Test. extendsMax(aColl); // compiles, T = S, extends T> = A final S s3 = Test. extendsMax(bColl); // compiles, T = S, extends T> = B final A a1 = Test. extendsMax(aColl); // compiles, T = A final B b1 = Test. extendsMax(bColl); // compiles, T = B final S s4 = Test. max(sColl); // compiles, T = S final S s5 = Test. max(aColl); // does not compile, T = S, T != A final S s6 = Test. max(bColl); // does not compile, T = S, T != B final S s7 = Test.max(aColl); // compiles, but because T = A, and A // can be assigned to S }
因此通配符允许一些灵活性。 虽然你可以省略通配符(说实话,我不能想到我需要通配符的地方),这是有原因的。
汤姆也不对。 您可以使用通配符向集合添加null
(如果集合首先支持add()
):
List extends Number> list = new ArrayList<>(); list.add(null); // compiles, and should execute just fine
并且因为add()
, remove()
和Collection
接口中的大多数其他mutator都是可选操作,如果参数刚刚声明为Collection
那么通过这些方法改变集合是不安全的。 此外,通常可以使用iterator().remove()
或类似的东西来删除集合中的元素,无论它们是否使用通配符声明,尤其是对于已经包含在Java Collections Framework中的元素。
因此,虽然通配符确实限制了您可以对集合执行的操作,但不应将其用作防止更改集合的方法。