数组 泛型 协变(转载)

1、数组的协变性

数组的协变性(covariant)是指:

如果类Base是类Sub的基类,那么Base[]就是Sub[]的基类。

而泛型是不可变的(invariant),List不会是List的基类,更不会是它的子类。

数组的协变性可能会导致一些错误,比如下面的代码:

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、泛型不是协变的

虽然将集合看作是数组的抽象会有所帮助,但是数组还有一些集合不具备的特殊性质。

Java 语言中的数组是协变的(covariant),也就是说,如果 Integer扩展了 Number(事实也是如此),那么不仅 Integer是 Number,而且 Integer[]也是 Number[],在要求 Number[]的地方完全可以传递或者赋予 Integer[]。(更正式地说,如果 Number是 Integer的超类型,那么 Number[]也是 Integer[]的超类型)。

您也许认为这一原理同样适用于泛型类型 —— List是 List的超类型,那么可以在需要 List的地方传递 List。不幸的是,情况并非如此。

不允许这样做有一个很充分的理由:

这样做将破坏要提供的类型安全泛型。

如果能够将 List赋给 List。

那么下面的代码就允许将非 Integer的内容放入 List

List li = new ArrayList();

List ln = li; // illegal

ln.add(new Float(3.1415));

时间: 2024-12-22 02:46:00

数组 泛型 协变(转载)的相关文章

.NET 4.0中的泛型协变和反变

随Visual Studio 2010 CTP亮相的C#4和VB10,虽然在支持语言新特性方面走了相当不一样的两条路:C#着重增加后期绑定和与动态语言相容的若干特性,VB10着重简化语言和提高抽象能力:但是两者都增加了一项功能:泛型类型的协变(covariant)和反变(contravariant).许多人对其了解可能仅限于增加的in/out关键字,而对其诸多特性有所不知.下面我们就对此进行一些详细的解释,帮助大家正确使用该特性. 背景知识:协变和反变 很多人可能不不能很好地理解这些来自于物理和

.NET 4.0中的泛型协变和逆变

随Visual Studio 2010 CTP亮相的C#4和VB10,虽然在支持语言新特性方面走了相当不一样的两条路:C#着重增加后期绑定和与动态语言相容的若干特性,VB10着重简化语言和提高抽象能力:但是两者都增加了一项功能:泛型类型的协变(covariant)和反变(contravariant).许多人对其了解可能仅限于增加的in/out关键字,而对其诸多特性有所不知.下面我们就对此进行一些详细的解释,帮助大家正确使用该特性. 背景知识:协变和反变 很多人可能不不能很好地理解这些来自于物理和

数组泛型

前言:大家都知道要定义如"T[]t = new T[10];"这种泛型数组是不行的,自己也找了不少方法.最后在<Thinking InJava>中吸取了一种很好的方法.现在分享给大家. ?源码: import java.lang.reflect.Array; public classArrayOfGeneric<T> { T[]ts; @SuppressWarnings("unchecked") publicArrayOfGeneric(Cl

js数组操作【转载】

用 js有很久了,但都没有深究过js的数组形式.偶尔用用也就是简单的string.split(char).这段时间做的一个项目,用到数组的地方很多,自以为js高手的自己居然无从下手,一下狠心,我学!呵呵.学了之后才知道,js数组的功能强大很,远比VB,C#强多了,大家慢慢看吧 1.数组的创建 var arrayObj = new Array(); //创建一个数组var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上限,是长度var array

JavaScript数组去重(转载)

转载自https://zhuanlan.zhihu.com/p/24753549 作者:TooBug 定义重复(相等) NaN 初看NaN时,很容易把它当成和null.undefined一样的独立数据类型.但其实,它是数字类型. console.log(typeof NaN); //number 根据规范,比较运算中只要有一个值为NaN,则比较结果为false,所以会有下面这些看起来略蛋疼的结论: // 全都是false 0 < NaN; 0 > NaN; 0 == NaN; 0 === Na

泛型(转载)

---恢复内容开始--- ------原文:http://www.cnblogs.com/lwbqqyumidi/p/3837629.html Java总结篇系列:Java泛型 一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: 1 public class GenericTest { 2 3 public static void main(String[] args) { 4 List list = new ArrayList(); 5 list.add("qqyum

泛型--协变与逆变(转)

对于泛型的知识,一直比较模糊,现在有机会整理一下,突发发现C#还有很多你不知道的东东,继续.NET FrameWork中泛型的协变与逆变: 1. 可变性的类型:协变性和逆变性 可变性是以一种类型安全的方式,将一个对象当做另一个对象来使用.如果不能将一个类型替换为另一个类型,那么这个类型就称之为:不变量.协变和逆变是两个相互对立的概念: 如果某个返回的类型可以由其派生类型替换,那么这个类型就是支持协变的 如果某个参数类型可以由其基类替换,那么这个类型就是支持逆变的. 2. C# 4.0对泛型可变性

站在巨著之上谈泛型(转载)

本系列内容,立足于两本巨著:<Thinking in Java>(第四版)和<Effective Java>(第二版).本系列内容出自这两本巨著,但是从另外一个角度阐释了泛型系统内容,你会收获一些不一样的知识体会.本系列内容包括以下八节: 第一节:<泛型的起源>,只有理解了泛型的产生背景和产生的原因,了解了泛型为解决什么问题而出现,你才能体会到它的作用. 第二节:<泛型的用武之处>,这一节内容是上一节内容的延伸,重点提出了“容器”这个概念.为下文埋下了伏笔.

JavaScript 数组操作函数--转载+格式整理

JavaScript 数组操作函数(部分)--转载+格式整理 今天看了一篇文章,主要讲的对常用的Js操作函数:push,pop,join,shift,unshift,slice,splice,concat的总结.身为一个有点完美主义的强迫症患者来说,原文的格式,差点杀死我.so,这篇文章就出来了……原文:传送门. 一.push 和 pop 这两个函数都是对数组从尾部进行压入或弹出操作. push(arg1,arg2,...)可以每次压入一个或多个元素,并返回更新后的数组长度. 注意:如果参数也是