Java Collections.max签名的说明

Java Collections.max签名的说明,java,generics,Java,Generics,我在读一篇关于Java泛型的文章时偶然发现了这个方法签名: static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll); staticGábor是正确的。通配符允许返回对象的静态类型与您输入的集合的声明参数类型不同。例如,给定这些类: interface S extends Comparable<S> {} class A im

我在读一篇关于Java泛型的文章时偶然发现了这个方法签名:

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

staticGábor是正确的。通配符允许返回对象的静态类型与您输入的集合的声明参数类型不同。例如,给定这些类:

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;
    }
}
由于
add()
remove()
,以及
Collection
接口中的大多数其他变体都是可选操作,因此,如果参数仅声明为
集合,则通过这些方法对集合进行任何变体都是不安全的。此外,通常可以使用
iterator().remove()
或类似的方法从集合中删除元素,而不管它们是否使用通配符声明,尤其是对于已经包含在Java集合框架中的元素


因此,虽然通配符确实限制了对集合的操作,但不应将其用作阻止对集合进行更改的方法。

例如,您希望返回一个
数字
,但您也希望使用
双精度
整数
集合。通过这种方式,您可以在呼叫站点指定电话号码:
max(doubles)
。感谢您的回复。但是,我认为如果我们将Collection作为参数,这仍然有效。我的怀疑是,在这种情况下,使用CollectionUsing通配符的唯一区别在于,它可以防止该方法无意中添加到集合或以其他方式改变集合,因为消费者需要super(始终记住PECS助记符!)您还可以看到它遵循PECS原则。Coll是T的提供者,因此它使用extends
Test。max(aColl);//不编译
当然不编译
T=S
,而
aColl
Collection
。但是正如您在后面提到的,您不需要使用
来显式地
t
true<因为
aColl
,code>T
将是
A
,而不是
S
因为作业。不管怎样,我现在明白了。谢谢你的详细回复!谢谢@user3580294。它以一种更清晰的方式呈现。我还忘记了变异的
remove
方法。@GáborBakos
Collections.swap(…)
Collections.sort(…)
也可以使用通配符类型。还有
clear()
删除所有元素。
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;
    }
}
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
}
List<? extends Number> list = new ArrayList<>();
list.add(null); // compiles, and should execute just fine