集合泛型定义问题怎么理解?
List list = new ArrayList<Integer>();//为什么能添加任何类型
List<String> list = new ArrayList<>();//只能添加String类型
回答:
List list = new ArrayList<Integer>();//为什么能添加任何类型
泛型只是在编译期检查类型,在运行时泛型已经不存在了,这个写法是在实例化的时候声明了泛型,但是赋值给list的时候泛型丢弃了,因为list的声明类型是 List,List本身不带泛型相当于List<Object>或者 List<?> 所以可以添加任何类型
List<String> list = new ArrayList<>();//只能添加String类型
这个写法相当于List<String> list = new ArrayList<String>();
,只是java8时加入的一个简化写法而已,效果是一样的
修正:是java7加入的语法糖,类型推断
回答:
要区分数组和泛型容器,那么就需要先理解以下三个概念:协变性(covariance)、逆变性(contravariance)和无关性(invariant)。
若类A是类B的子类,则记作A≦B。设有变换f(),则有以下定律:
- 当A≦B时,有f(A)≦f(B),则称变换f()具有协变性。
- 当A≦B时,有f(B)≦f(A),则称变换f()具有逆变性。
- 如果以上两者皆不成立,那么称变换f()具有无关性。
在Java语言中,数组具有协变性,而泛型具有无关性,示例代码如下所示:
Object[] array = new Integer[1]; //这里ide会有红色下划线,表示编译错误。
ArrayList<Object> list = new ArrayList<Integer>();
以上这两行代码,数组正常编译通过,而泛型抛出了编译期错误,应用之前提出的概念对代码进行分析,可知以下推论:
数组的变换可以表达为f(A)=A[],通过之前的示例
可以得出以下推论:
f(String) = String[] 以及 f(Object) = Object[]
通过代码验证,String[]≦Object[]是成立的,由此可见,数组具有协变性。ArrayList泛型的变换可以表达为f(A)=ArrayList
得出以下推论:
f(String) = ArrayList<String> 以及 f(Object) = ArrayList<Object>
最终得出结论,数组具备协变性,而泛型具备无关性。
所以,为了让泛型具备协变性和逆变性,Java引入了有界泛型的概念。
除了协变性的不同,数组还是具象化的,而泛型不是。
什么是具象化(也可以称之为具体化,物化)?在《Java语言规范》里,明确地规定了具象化类型的定义:
完全在运行时可用的类型被称为具象化类型(refiable type),会做这种区分是因为有些类型会在编译过程中被擦除,并不是所有的类型都在运行时可用。它包括:
- 非泛型类声明,接口类型声明。
- 所有泛型参数类型为无界通配符(仅用‘?’修饰)的泛型参数类。
- 原始类型。
- 基本数据类型。
- 其元素类型为具象化类型的数组。
- 嵌套类(内部类、匿名内部类等,例如java.util.HashMap.Entry),并且嵌套过程中的每一个类都是具象化的。
无论是在编译时还是运行时,数组都能确切地知道自己所属的类型。但是泛型在编译时会丢失部分类型信息,在运行时,它又会被当作Object处理。
Java的泛型最后都被当作上界 `(? extend Type )`
处理了。
换言之,数组必须清楚地知道自己内部元素的类型,并且会一直保存这个类型信息,在添加元素的时候,该信息会被用于做类型检查,而泛型的类型是不确定的。所以,在编译器层面就杜绝了这个问题的发生。这在《Java语言规范》里有明确地说明:
If the element type of an array were not reifiable,the virtual machinecould not perform the store check described
in the preceding paragraph.This is why
creation of arrays of non-reifiable types is forbidden.
Onemay declare variables of array types whose element
type is not reifiable,but any attempt to assign them a value will
give rise to an uncheckedwarning.
如果数组的元素类型不是具象化的,那么虚拟机将无法应用在前面章节里描述过的存储检
查。这就是为什么创建(实例化)非具象化的数组是不允许
的。你可以定义(声明)一个元素类型是非具象化的数组类
型,但任何试图给它分配一个值的操
作,都会产生一个unchecked warning。存储检查:
这里涉及Array的基本原理,可以自行参阅《Java语言规范》
泛型具有无关系。
回答:
因为 List 啥都能添加,List<String> 只能添加 String
以上是 集合泛型定义问题怎么理解? 的全部内容, 来源链接: utcz.com/p/944971.html