簡體   English   中英

Collections.max 簽名說明

[英]Explanation of the Collections.max signature

當我偶然發現這個方法簽名時,我正在閱讀一篇關於 Java 泛型的文章:

static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll);

我不明白的部分是為什么我們需要擁有

Collection<? extends T> coll

不會

Collection<T> coll

也是嗎?

有人可以解釋為什么下面的簽名是不夠的嗎?

static <T extends Object & Comparable<? super T>> T max(Collection<T> coll);

提前感謝您的回復。 這讓我困惑了很長一段時間。。

加博爾是對的。 通配符允許返回對象的靜態類型與您輸入的集合的聲明參數類型不同。 例如,給定這些類:

interface S extends Comparable<S> {}
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 extends Comparable<? super T>> T extendsMax(
            Collection<? extends T> coll) {
        return null;
    }

    @Nullable
    static <T extends Comparable<? super T>> T max(Collection<T> coll) {
        return null;
    }
}

觀察哪些調用 compile 哪些調用不調用:

public static void main(String[] args) {
    final Collection<S> sColl = new ArrayList<>();
    final Collection<A> aColl = new ArrayList<>();
    final Collection<B> bColl = new ArrayList<>();

    final S s1 = Test.<S> extendsMax(sColl); // compiles, T = S, <? extends T> = S
    final S s2 = Test.<S> extendsMax(aColl); // compiles, T = S, <? extends T> = A
    final S s3 = Test.<S> extendsMax(bColl); // compiles, T = S, <? extends T> = B
    final A a1 = Test.<A> extendsMax(aColl); // compiles, T = A
    final B b1 = Test.<B> extendsMax(bColl); // compiles, T = B

    final S s4 = Test.<S> max(sColl); // compiles, T = S
    final S s5 = Test.<S> max(aColl); // does not compile, T = S, T != A
    final S s6 = Test.<S> 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接口中的大多數其他修改器都是可選操作,所以如果參數只是聲明為Collection那么通過這些方法改變集合無論如何都是不安全的。 此外,通常可以使用iterator().remove()或類似的東西從集合中刪除元素,而不管它們是否使用通配符聲明,尤其是對於已經包含在 Java 集合框架中的元素。

因此,雖然通配符確實限制了您可以對集合執行的操作,但不應其用作防止更改集合的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM