Collections.max签名的解释 [英] Explanation of the Collections.max signature

查看:89
本文介绍了Collections.max签名的解释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  static< T extends Object& amp; amp; amp; ;可比< ;? super T>> T max(Collection<?extends T> coll); 

我没有得到的部分是为什么我们需要有

 收藏<?延伸T> coll 

不会

 收集和LT; T> coll 

可以吗?

可以有人请解释为什么以下签名是不够的?

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

预先感谢您的回复。这让我很困惑,现在已经有相当一段时间了。

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

  interface S扩展了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;


$ / code $ / pre

和这个类:

  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<>();
最终集合< A> aColl = new ArrayList<>();
最终集合< B> bColl = new ArrayList<>();

final S s1 = Test。< S> extendsMax(sColl); //编译,T = S,<?延伸T> = S
final S s2 = Test。< S> extendsMax(aColl); //编译,T = S,<?延伸T> = A
final S s3 = Test。< S> extendsMax(bColl); //编译,T = S,<?延伸T> = B
final A a1 = Test。< A> extendsMax(aColl); //编译,T = A
final B b1 = Test。< B> extendsMax(bColl); //编译,T = B

final S s4 = Test。< S> MAX(sColl); //编译,T = S
final S s5 = Test。< S> MAX(aColl); //不编译,T = S,T!= A
final S s6 = Test。< S> MAX(bColl); //不编译,T = S,T!= B

final S s7 = Test.max(aColl); //编译,但是因为T = A,并且A
//可以分配给S
}

所以通配符允许一些灵活性。虽然你可以忽略通配符(老实说,我不能想到一个需要通配符的地方),但是有一个原因。 p>




汤姆也是不正确的。您可以使用通配符添加 null 集合(如果集合首先支持 add()):

 列表< ;?扩展Number> list = new ArrayList<>(); 
list.add(null); //编译,并且应该执行得很好

因为 add() remove(),并且 Collection 接口中的大多数其他修改器都是可选操作,它如果参数只是声明为 Collection ,那么通过这些方法无论如何都不会改变集合。另外,通常可以使用 iterator()。remove()或类似的东西来删除集合中的元素,而不管它们是否用通配符声明,尤其是已经包含在Java集合框架中。



因此,尽管通配符限制了您对集合可以执行的操作,但它应该不是用作阻止对集合进行更改的方式。


I was reading an article on Java Generics when I stumbled on this method signature:

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

The part that I don't get is why we need to have

Collection<? extends T> coll

wouldn't

Collection<T> coll

do as well?

Could someone please explain why the following signature is not adequate?

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

Thanks in advance for your replies. This keeps puzzling me for quite some time now..

解决方案

Gábor is correct. The wildcard allows the static type of the returned object to differ from the declared parameter type of the collection you input. For example, given these classes:

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;
    }
}

And this class:

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;
    }
}

Observe what calls compile and what calls do not:

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
}

So the wildcard allows for some flexibility. While you can omit the wildcard (and to be honest, I can't think of a place off the top of my head where the wildcard is required), there is a reason it is there.


Tom is also incorrect. You can add null to collections with a wildcard (if the collection supports add() in the first place):

List<? extends Number> list = new ArrayList<>();
list.add(null); // compiles, and should execute just fine

And because add(), remove(), and most other mutators in the Collection interface are optional operations, it wouldn't be safe to mutate the collection anyways through those methods if the parameter is just declared as a Collection. In addition, it's generally possible to use iterator().remove() or something of the sort to remove elements from collections regardless of whether they were declared with a wildcard, especially for the ones already included in the Java Collections Framework.

So while a wildcard does limit what you can do with a collection, it should not be used as a way to prevent changes to a collection.

这篇关于Collections.max签名的解释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆