记得以前面试的时候曾被问过一个问题:数组和List的区别是什么?当时答的无非就是效率,容量固定,List不能存基本类型等等。当Java发展到了1.5之后,出现了泛型版本的List,又为这个问题的解答加入了一笔。下面就来讲一下与这个话题相关的内容。
1. 数组的协变性。
数组的协变性(covariant)是指如果类Base是类Sub的基类,那么Base[]就是Sub[]的基类。而泛型是不可变的(invariant),List<Base>不会是List<Sub>的基类,更不会是它的子类。数组的协变性可能会导致一些错误,比如下面的代码:
public static void main(String[] args) {
Object[] array = new String[10];
array[0] = 10;
}
它是可以编译通过的,因为数组是协变的,Object[]类型的引用可以指向一个String[]类型的对象。但是运行的时候是会报出如下异常的:
Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer
原因就像呼吸一样简单。
但是对于泛型就不会出现这种情况了:
public static void main(String[] args) {
List<Object> list = new ArrayList<String>();
list.add(10);
}
这段代码连编译都不能通过。
2. 数组的具体化。
第二个要讲的问题是数组是具体化的(reified),而泛型在运行时是被擦除的(erasure)。这句话的意思是数组是在运行时才去判断数组元素的类型约束,而泛型正好相反,在运行时,泛型的类型信息是会被擦除的,只有编译的时候才会对类型进行强化。
所以上面的例子中,数组的方法会在运行时报出ArrayStoreException,而泛型根本无法通过编译。
3. 泛型与数组的结合。
这个问题的标题有些误导,其实泛型与数组根本没有任何结合的可能性。List<E>[]、List<Integer>[]、或者E[]的写法都是错误的。因为这些方法无法提供类型的安全性。我们来分别举2个例子来说明它们会导致的错误。
public void testMethod1() {
List<Integer>[] array = new List<Integer>[10];
List<String> list = new ArrayList<String>();
Object[] objs = array;
objs[0] = list;
}
这段代码假设array这个泛型数组是可以被创建的,那么它就可以被Object[]类型的变量引用,进而导致了array中的元素变成了List<String>类型了,发生了类型错误。
第二个例子是关于类型参数数组的:
public <E> void testMethod2(E e) {
E[] array = new E[10];
Object[] objs = array;
objs[0] = e;
objs[1] = "string";
objs[2] = 10;
objs[2] = true;
}
与上边的那个例子相似,array可以放入任何类型的元素了,这个是很不安全的。
这里有一个例外的情况可以说一下,无限制通配符类型的泛型是可以创建泛型数组的。
List<?>[] listArray = new List<?>[10];
分享到:
相关推荐
泛型数组的创建
数组与泛型的关系还是有点复杂的,Java 中不允许直接创建泛型数组。本文分析了其中原因并且总结了一些创建泛型数组的方式。具有很好的参考价值。下面跟着小编一起来看下吧
java泛型源码Java泛型用法 步骤1 原始类型有问题。 第2步 使用泛型类型。 第三步 车库和车辆。 原始类型。 第四步 首先尝试生成车库。 木星在我的车库里。 第5步 泛型上限。 第6步 TripleGarage 步骤7 试图使用泛型...
NULL 博文链接:https://xnn.iteye.com/blog/572501
java泛型例子 内涵泛型类,泛型接口,泛型方法,泛型通配符使用,泛型上界下界,泛型数组,嵌套泛型等,很详细。放入myeclipse可用,已测试。
JAVA泛型源代码实现以下功能:返回数组元素的最大值/最小值下标;判断数组元素是否按升序排列;T对象数组排序;二分法查找key元素;
运用Java编程,自定义数组大小,解决在数组中加入元素,获取元素;按指定位置删除元素,修改元素;清空数组;数组的排序。
java 泛型详解 实例 class Point class Notepad,V>{ // 此处指定了...通配符、受限泛型、泛型无法向上转型、泛型接口、泛型方法、通过泛型方法返回泛型类型实例、使用泛型统一传入的参数类型、泛型数组、泛型的嵌套设置
Java SE编程入门教程 java泛型(共11页).pptx Java SE编程入门教程 java封装继承多态(共56页).pptx Java SE编程入门教程 java集合(共38页).pptx Java SE编程入门教程 java接口(共21页).pptx Java SE编程入门...
主要介绍了java 用泛型参数类型构造数组详解及实例的相关资料,需要的朋友可以参考下
本文主要介绍了java数组、泛型、集合在多态中的使用及对比。具有很好的参考价值,下面跟着小编一起来看下吧
Java 课件 (包括基础语法,数组与语句,面向对象编程,java异常处理,java常用基础类,java集合与泛型)
(调用的是泛型方法)泛型与数组(只有可具体化类型可以创建数组):数组是协变类型 String数组是Object数组的字类型 但是对于list而言,则不是什么是方
主要介绍了Java封装数组之改进为泛型数组操作,结合实例形式详细分析了Java封装数组为泛型数组相关原理、操作技巧与注意事项,需要的朋友可以参考下
但其实Java泛型还是有挺多tricky的东西的,编译器在背后为我们做了很多事。下面我们来看看有关Java泛型容易忽视的点。 泛型不支持协变 什么是协变?举个例子。 class Fruit{} class Apple extends Fruit...
完整超详细版 耿祥义 Java大学实用教程(第2版)PPT课件 第05章 继承 接口与泛型 (共104页).ppt 完整超详细版 耿祥义 Java大学实用教程(第2版)PPT课件 第06章 字符串和正则表达式 (共62页).ppt 完整超详细版 ...
6. 与旧代码交互 6.1. 在泛型代码中使用老代码 6.2. 擦除和翻译(Erasure and Translation) 6.3. 在老代码中使用泛型代码 7. 要点(The Fine Print) 7.1. 一个泛型类被其所有调用共享 7.2. 转型和instanceof 7.3. 数组...
java反射全解(反射原理+反射API详解+反射与数组+反射与泛型+反射源码与性能开销+反射优缺点+反射与内省)
Java泛型 14-05-2019 命名约定和包,“静态”和“最终”关键字。 21-05-2019 Java 集合 03-06-2019 JavaFX 第 14 节 基本输入和输出,包括 java.util 第 15 节 Java 中的并发 第 16 节 Lambda 表达式 第 17 节 常用...
介绍了Java编程思想里的泛型实现一个堆栈类,有需要的朋友可以参考一下