Java 仿制药->;多极同态->;误解或只是它的工作原理 让我们考虑代码块: List<List<Object>> list = new ArrayList(); list.add(new ArrayList<Object>); //Line 2 list.add(new LinkedList<Object>); //Line 3 list.add(new LinkedList<Date>); //Line 4

Java 仿制药->;多极同态->;误解或只是它的工作原理 让我们考虑代码块: List<List<Object>> list = new ArrayList(); list.add(new ArrayList<Object>); //Line 2 list.add(new LinkedList<Object>); //Line 3 list.add(new LinkedList<Date>); //Line 4,java,generics,generic-list,generic-programming,Java,Generics,Generic List,Generic Programming,输出:1 将编译,意味着没有类型安全性。为什么?即使是列表-原始类型和数组列表参数化类型,任何方法都是无用的。为什么? 据我所知,多形赋值在泛型中不起作用 那是错误的。类型为ArrayList的引用和类型为LinkedList的引用都是类型为List的引用的子类型 无论日期是对象的子类型,第4行都不会编译 LinkedList类型的引用不是List类型的引用的子类型(即使T是E的子类型) 即使列表-原始类型和ArrayList参数化类型 您声明的引用类型为列表。这在概念上与声明List的引用类型

输出:
1

将编译,意味着没有类型安全性。为什么?即使是
列表
-原始类型和
数组列表
参数化类型,任何方法都是无用的。为什么?

据我所知,多形赋值在泛型中不起作用

那是错误的。类型为
ArrayList
的引用和类型为
LinkedList
的引用都是类型为
List
的引用的子类型

无论日期是对象的子类型,第4行都不会编译

LinkedList
类型的引用不是
List
类型的引用的子类型(即使
T
E
的子类型)

即使列表-原始类型和ArrayList参数化类型

您声明的引用类型为
列表
。这在概念上与声明
List
的引用类型相同。对任何方法(weather static或instance方法)的调用都在编译时使用引用类型进行解析。由于引用类型是
List
(即原始列表),编译器将允许您向列表中添加任何类型的对象。编译类时,编译器将语句
ArrayList
转换为
ArrayList
。这称为
类型擦除
。这也是为什么您在运行时不会遇到任何问题的原因

第一个问题:

List list = new ArrayList<String>();
list.add(new Integer(1));
所以规则是:子类可以做超类所能做的一切(甚至更多)

A
B
的子类,如果
A
B
的子类

这是因为A可以做B可以做的任何事情。无论您在哪里使用
B
,您都可以使用
A

例如:

List<Object> lo
ArrayList<Object> alo
List lo
ArrayList alo
ArrayList alo
可以做任何事情
List lo
可以做,因此它是一个子类

但是:

A
不是
A
的子类,即使X是Y的子类

这是因为
A
不能做
A
能做的一切

在下列情况下:

List<Object> lo
List<Date> ld
List lo
列表ld
List lo
可以向lo添加任何对象,但是
List ld
只能添加日期,因此它不能是子类

第二个问题:

List list = new ArrayList<String>();
list.add(new Integer(1));
List List=new ArrayList();
添加(新整数(1));
是的,这很糟糕,不起作用。这就是你得到警告的原因

List
声明在这里是确定
List
类型和您可以使用它做什么的重要部分。在运行时,
ArrayList
看起来就像一个
ArrayList
,这是因为有一种叫做类型擦除的东西,所以这也不会阻止添加不好的东西

列表是原始类型。对泛型类型列表的引用应为
参数化

警告:

子类可以做超类所能做的一切的陈述是设计意图的一般陈述,而不是字面上的真实。当然,你可以找到反例

据我所知,多形赋值在泛型中不起作用

实际上,您正在谈论泛型和继承

因此,如果您有
列表
即动物列表,您可以在列表下添加任何动物,如猫、狗,但您不能将
狗列表
分配给
动物列表

这是一个例子

psvm{
List<Dog> list1 = new ArrayList<Dog>();
list1.add(new Dog());
method1(list1);// compilation error
}

public static void method1(List<Animal> list1) {
list1.add(cat); // Good
list1.add(dog); // Good
}

list.add(新列表)您是如何实例化接口的?这是您自己的类,而不是Java接口
列表
?请查看我的答案,如果您需要任何澄清,请告诉我。另请参阅和。泛型不变性仅适用于泛型部分。类和接口以正常方式工作。一个
ArrayList
是一个
列表
。仍然没有得到我所问的答案:我有列表,所以为什么列表的泛型可以被polymorphical子类化,我的意思是->结果是列表-可以用子类替换-不能认为列表这是列表的泛型,不能更改。这是如何发生的???
子类可以完成超类所能做的一切
。不是真的。考虑一个类<代码> a <代码>,该方法具有不具有任何访问说明符的方法(例如,无效方法())。与
A
位于同一包中的子类可以执行
A
可以执行的任何操作。与
A
不同的包中的子类不能做
A
可以做的任何事情,因为它不会继承
methodA()
很好的一点-我没有想到它,但由于Java的奇异性,它是一种边缘情况。我认为把它添加到答案中会使事情变得混乱。但这是你的答案所基于的主要前提。不正确的前提会使论点/结论不正确。:)不,如果反例不在讨论范围内,则不在讨论范围内。我的论点是关于设计原则的,而不是关于具体的实现细节。深入研究细节会模糊这一点。但是,无论如何,你的案例很有趣。你正在扩大范围来证明你的答案。这个问题被标记为
java
,我的反例在很大程度上在范围内:)仍然没有得到我所问的答案:我有List,所以为什么List的泛型可以被polymorphical子类化->结果是List-可以用subclass替换-不能认为List是泛型的吗列表,并且无法更改。这是如何发生的???第二个问题:为什么copmpiler允许您编写List=newArrayList();特别是ArrayList(),即使它是usless,我可以把任何我想要的东西放到ArrayList的字符串中???仍然没有得到答案我问:我有List,所以为什么List的泛型可以是polymorphical子类->结果是List-可以b吗
psvm{
List<Dog> list1 = new ArrayList<Dog>();
list1.add(new Dog());
method1(list1);// good
}

public static void method1(List<? extends Animal> list1) {
list1.add(cat); // compilation error
list1.add(dog); // compilation error
}