List<? 扩展超类型>如果从流中收集,可以包含多个不同的子类型



Java不允许在<?扩展superType>是列表的已声明泛型类型。因为在这种情况下,列表被视为只读,以强制它只包含其动态类型的对象。

//1注释的行将返回编译错误。

我的问题是:

  • 为什么行会被//2编译?它最终将多个子类型对象放入列表中
  • 如果这里没有问题,那么为什么要在//1处抛出编译错误呢
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class Scratch {
static class Animal {}
static class Dog extends Animal {}
static class Cat extends Animal {}
public static void main(String[] args) {
List<Cat> cats = new ArrayList<>();
List<Dog> dogs = new ArrayList<>();
//List<? extends Animal> animalsOfTwoTypes = new ArrayList<Dog>(); 
//animalsOfTwoTypes.add(new Dog()); //1

List<? extends Animal> animals = Stream.of(cats, dogs)  //2
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
}

它最终将多个子类型对象放入列表中。

是的,但它们都是Animal的亚型。您还没有指定列表中元素的类型;编译器所要做的就是检查列表的结果类型是否与变量类型兼容。

你本可以写:

List<Animal> animalsWithoutWildcard = Stream.of(cats, dogs)  //2
.flatMap(Collection::stream)
.collect(Collectors.toList());

这也很好。然后

List<? extends Animal> animals = animalsWithoutWildcard;

也可以,因为Animal的列表也可以用作从中获取Animal实例的列表:animalsAnimal实例的生产者,而animalsWithoutWildcard既是Animal实例的又是消费者

重点不是List<? extends Animal>变量引用的东西不能添加东西(除了null(,而是不能通过该变量添加东西。因此:

System.out.println(animals.size());     // N
animalsWithoutWildcard.add(new Dog());  // fine
System.out.println(animals.size());     // N + 1
// but this is an error, even though it's the same list.
animals.add(new Dog());

相关内容

  • 没有找到相关文章

最新更新