是List&lt; Double&gt; List的子类型<?扩展Number&gt;为什么呢? [英] Is List&lt;Double&gt; a subtype of List&lt;? extends Number&gt; and why?

查看:173
本文介绍了是List&lt; Double&gt; List的子类型<?扩展Number&gt;为什么呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我所知道的:

  1. DoubleNumber的子类型,而List<Double>不是List<Number>的子类型.
  2. List<Dog>不是List<Animal>的子类型,因为您可以将Cat添加到List<Animal>,但是不能使用List<Dog>做到这一点.
  3. List<? extends Number>表示此列表可以存储Number类型的变量和Number子类型的变量. List<Double>表示此列表可以存储Double类型的变量.
  1. Double is a subtype of Number and List<Double> is not a subtype of List<Number>.
  2. List<Dog> is not a subtype of List<Animal> because you can add Cat to List<Animal> but you can't do that with List<Dog>.
  3. List<? extends Number> means this list can store variables of type Number and variables of subtype of Number. List<Double> means this list can store variables of type Double.

如果以上任何内容有误,请纠正我,然后List<Double>List<? extends Number>的子类型,为什么?

Please correct me if anything above is wrong and then Is List<Double> a subtype of List<? extends Number> and why?

推荐答案

还应添加一些要点

  1. 在运行时List<Double>List<? extends Number>List<?>List<Object>都相同.通用参数根本没有编译.泛型的所有魔力都在编译时很有趣.这也意味着,如果List为空,则不知道通用参数是什么!

  1. At runtime List<Double>, List<? extends Number>, List<?> and List<Object> are all identical. The generic parameter is not compiled at all. All the magic with generics is all compile time fun. This also means that if you have a List that is empty you have no idea what the generic parameter is!

尽量不要将通用参数视为子类型",通用参数的实际含义是"使用通用参数",因此在此情况"列表使用 Number ".一个很好的例子是 HashMap源,如果您查看它的内部工作原理,它实际上存储的是Entry数组,并且所有条目都存储有键和值.当您查看泛型的更复杂用法时,偶尔会看到这种用法.

Try not to think of the generic parameter as a "Subtype", the generic parameter really means "the class uses a generic parameter" so in this case "the list uses a Number". A good example of this is the HashMap source, if you have a look into the inner workings of it, it is actually storing an array of Entry, and the entries all have keys and values stored on them. When you look at more complex uses of generics you occasionally see this sort of use.

List的情况下,通用参数意味着列表存储了该类型的对象,可能是该对象根本没有存储过通用参数类型的对象!像这样:

In the situation of a List the generic parameter means that the list stores that type of object, it could be that the object never stores an object of the type of the generic parameter at all! Like this:

public class DummyIterator<O> implements Iterator<O>{
    public boolean hasNext() {
        return false;
    }

    public O next() {
        return null;
    }
}

  • List<? extends Number>的实际含义是什么?好吧,对于大多数用途,它与List<Number>几乎相同.不过请记住,在这种情况下,您说出?几乎是说我不在乎类型":

  • What does List<? extends Number> actually mean? Well it is pretty much the same as List<Number> for most uses. Keep in mind though that by saying ? you are pretty much saying 'I don't care about the type' which shows itself in this situation:

    List<Double> doubles = new ArrayList<Double>();
    List<? extends Number> numbers = doubles;
    numbers.add(new Double(1));  //COMPILE ERROR
    Number num = numbers.get(0);
    

    所以我们不能将Double添加到<? extends Number>.但是对于这个例子:

    So we can't add a Double to a <? extends Number>. But for this example:

    List<Double> doubles = new ArrayList<Double>();
    List<Number> numbers = doubles; //COMPILE ERROR
    numbers.add(new Integer(1));
    Number num = numbers.get(0);
    

    您不能将List<Double>分配给List<Number>,这正如您明确告诉的那样,即列表仅使用数字类型

    You can't assign the List<Double> to a List<Number> which makes sense as you are specifically telling it, that lists use only Number types

    那么您应该在哪里使用??确实在任何您可以说我不在乎通用参数"的地方,例如:

    So where should you use a ?? well really anywhere you could say "I don't care about the generic parameter" so for instance:

    boolean equalListSizes(List<?> list1, List<?> list2) {
      return list1.size() == list2.size();
    }
    

    仅当您不使用通用参数修改对象时,才使用? extends Number格式类型.例如:

    You would use the ? extends Number type of format only where you are not modifying the object using the generic parameter. so for instance:

      Number firstItem(List<? extends Number> list1) {
        return list1.get(0);
      }
    

  • 而不是使用?? extends Number格式,而是尝试在类/方法上使用泛型,在大多数情况下,这也使您的代码也更具可读性!:

  • Instead of using the ? and ? extends Number formats try using generics on the class / method instead, in most cases it makes your code more readable as well!:

    <T extends Number> T firstItem(List<T> list1) {
      return list1.get(0);
    }
    

    班级:

    class Animal{}
    class Dog extends Animal{}
    class AnimalHouse<A extends Animal> {
        List<A> animalsInside = new ArrayList<A>(); 
        void enterHouse(A animal){
            animalsInside.add(A);
        }
    
        A leaveHouse() {
            return animalsInside.remove(0);
        }
    }
    AnimalHouse<Dog> ah = new AnimalHouse<Dog>();
    ah.enterHouse(new Dog());
    Dog rufus = ah.leaveHouse();
    

  • 作为围绕泛型的一种加倍考虑,您还可以参数化方法以返回特定的类.一个很好的例子是junit中的any()方法和空列表集合:

  • As a bonus thought around generics you can also parameterise methods to return a particular class. A good example of this is the any() method in junit and the empty list collection:

    Dog rufus = Matchers.<Dog>any();
    List<Dog> dogs = Collections.<Dog>emptyList();
    

    此语法允许您指定对象的返回类型.有时非常有用的知识(使某些转换变得多余)!

    This syntax allows you to specify the return type of an object. Sometimes quite useful to know (makes some casting redundant)!

    这篇关于是List&lt; Double&gt; List的子类型<?扩展Number&gt;为什么呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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