Java 什么';s数组声明和集合声明之间的区别

Java 什么';s数组声明和集合声明之间的区别,java,generics,collections,typesafe,Java,Generics,Collections,Typesafe,有人能告诉我为什么集合必须声明为条件2吗?谢谢在您的案例1中,您实际上是在创建一个ArrayList来保存各种汽车对象,然后尝试为这个变量分配一个轿车的ArrayList。这在其核心不起作用,因为你要从大到小(轿车是汽车,但汽车可能不是轿车) 基本上,在案例1中,您的carList不起作用,因为使用泛型,任何汽车都应该能够放入carList。这意味着我可以在添加轿车后立即调用carList.add(new Compact();) 案例2遵循本公约 在使用泛型时,我喜欢这样想:在案例1中,您实际上

有人能告诉我为什么集合必须声明为条件2吗?谢谢在您的案例1中,您实际上是在创建一个
ArrayList
来保存各种汽车对象,然后尝试为这个变量分配一个轿车的
ArrayList
。这在其核心不起作用,因为你要从大到小(轿车是汽车,但汽车可能不是轿车)

基本上,在案例1中,您的
carList
不起作用,因为使用泛型,任何汽车都应该能够放入
carList
。这意味着我可以在添加轿车后立即调用
carList.add(new Compact();

案例2遵循本公约


在使用泛型时,我喜欢这样想:在案例1中,您实际上是在创建两种不同类型对象的实例。想象一下
ArrayListCar
ArrayListSedan
,如果您愿意的话。每个对象都专门用于获取它们的特定参数。我知道,这会让人困惑,因为数组可以工作,但这很简单这就是它的设计方式。

轿车[]
汽车[]
的一个子类型。但这对类型安全有非常负面的影响,因为以下代码是合法的:

int SIZE = 10;
Car[] carArray = new Sedan[SIZE];
此代码在运行时导致ArrayStoreException,因为假定仅包含轿车的数组将包含非轿车

泛型的目标是拥有类型安全的集合。因此,我们决定设计它们,以便在编译时而不是运行时检测到上述问题。集合的使用比数组多得多,拥有类型安全的集合是件好事


因此他们决定
列表
不会是
列表

而是泛型中的类型安全。假设它是正确的:

Sedan[] sedans = new Sedan[10];
Car[] cars = sedans; // legal, since Sedan[] extends Car[]
cars[0] = new Car(); // Houston, we have a problem
List dogs=new ArrayList();
列出动物=狗;
添加(新的Cat());
您当然可以将一个新的cat对象添加到类型Animal的列表中,但是如果动物指的是狗,您将把一只猫和一群狗弄乱,这是非常危险的,为了避免这种情况,泛型的类型安全只允许声明类型与对象类型匹配。

这编译:

List<Dog> dogs = new ArrayList<Dog>();
List<Animal> animals = dogs;
animals.add(new Cat());
List这个和这个详细解释。Josh Bloch使用泛型的PECS原则解释了主要思想

List<? extends Car> carList = new ArrayList<Sedan>();
我最关心的是,您如何与存储在容器中的数据交互,作为生产者或消费者

另一个问题是,类型安全检查、运行时间或编译时间是什么时候?考虑以下事项:

Producer Extends > Consumer Super  [PECS]
//在运行时捕获数组类型安全错误
Object[]objArray=new Long[3];
objArray[0]=“我是一个字符串”;
对象notANumber=objArray[0];
//运行时异常
长编号=(长)编号;
//编译时捕获的泛型类型错误
//在新的ArrayList()中使用pecs原则;
列表=新的ArrayList();
list.add(“不是数字”);//编译时错误
列表。添加(长值(42L));
Long wontWork=list.get(0);//编译时错误
工作数量=列表。获取(0);

@Takendarkk我知道这是泛型,但泛型指的是使用尖括号表示类型,不是关于超类和子类,是吗?@haifzhan你真的认为超/子类与类型无关吗?@Takendarkk我不是说超类和子类与类型无关,我是问你它们为什么相关对于泛型,我希望得到答案数组实现被广泛认为是一个错误,谢天谢地,在集合中没有重复
Producer Extends > Consumer Super  [PECS]
// array type safety errors caught at run time
Object[] objArray = new Long[3];
objArray[0] = "i'm a string";
Object notANumber = objArray[0];

// run time exception
Long number = (Long)notANumber;

// generic type errors caught at compile time
// use pecs principle in new ArrayList<...>();
List<Number> list = new ArrayList<Number>();
list.add("not a number"); // compile time error
list.add(Long.valueOf(42L));

Long wontWork = list.get(0);  // compile time error
Number works = list.get(0);