java 泛型没有协变类型, 所以要重用extends, 但使用List<? extends Fruit> 可以是ArrayList<Fruit>()、ArrayList<Apple>()、ArrayList<Orange>(), 因此不能add元素进去
class Fruit{}
class Apple extends Fruit{}
class SubApple extends Apple{}
class Orange extends Fruit{}
class Holder<T>{
private T value;
public Holder(){}
public Holder(T value){this.value = value;}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public boolean equals (Object obj){
return value.equals(obj);
}
}
public class CovarianArrays {
public static void main(String[] args) {
Fruit [] fruitArray = new Apple[10];
fruitArray[0] = new SubApple();
//数组有协变类型,能放入SubApple
//编译时正常。运行时错误 ArrayStoreException 数组在运行时检查类型
//fruitArray[0] = new Fruit();
//fruitArray[1] = new Orange();
//编译时就出错
//List<Fruit> fruitList = new ArrayList<Apple>();
List<Apple> fruitList = new ArrayList<Apple>();
fruitList.add(new Apple());
//只能是Apple,泛型没有协变类型
//fruitList.add(new SubApple());
List<? extends Fruit> fruitExtendList = new ArrayList<Apple>();
//连Object都不行,只能是无意义的null
//fruitExtendList.add(new Apple());
//fruitExtendList.add(new Object());
fruitExtendList.add(null);
List<? extends Fruit> fruitAsList = Arrays.asList(new Apple());
Apple a = (Apple) fruitAsList.get(0);
//以下两个方法的参数都是Object
fruitAsList.contains(new Apple());
int i =fruitAsList.indexOf(new Apple());
System.out.println(i);//-1 不存在
List<? super Apple> supList = new ArrayList<Apple>();
supList.add(new Apple());
supList.add(new SubApple());
//supList.add(new Fruit());
Holder<Apple> holdApple = new Holder<Apple>(new Apple());
Apple a1 = holdApple.getValue();
System.out.println(a1); //com.Array.Apple@10b30a7
//Holder<Fruit> holdFruit = holdApple;
Holder<? extends Fruit> holdFruit = holdApple;
Fruit f1 = holdFruit.getValue();
System.out.println(f1); //com.Array.Apple@10b30a7
Apple a2 = (Apple) holdFruit.getValue();
System.out.println(a2);
Orange o1 = (Orange) holdFruit.getValue(); //运行时出错ClassCastException
System.out.println(o1);
//不能调用setValue()
//holdFruit.setValue(new Orange());
}
}
参考:

java 泛型没有协变类型, 所以要重用extends, 但使用List<? extends Fruit> 可以是ArrayList<Fruit>()、ArrayList<Apple>()、ArrayList<Orange>(), 因此不能add元素进去的更多相关文章
- Java泛型-内部原理: 类型擦除以及类型擦除带来的问题
一:Java泛型的实现方法:类型擦除 大家都知道,Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,正确理解泛型概念的首要前提是理解类型擦除.Java的泛型基本上都是在编译 ...
- java泛型总结(类型擦除、伪泛型、陷阱)
JDK1.5开始实现了对泛型的支持,但是java对泛型支持的底层实现采用的是类型擦除的方式,这是一种伪泛型.这种实现方式虽然可用但有其缺陷. <Thinking in Java>的作者 B ...
- Java泛型的协变
在上篇<Java泛型的基本使用>这篇文章中遗留以下问题,即将子类型也能添加到父类型的泛型中,要实现这种功能必须借助于协变. 实验准备 现在在上篇文章展示的Decorator类型的基础上,增 ...
- Java泛型的协变与逆变
泛型擦除 Java的泛型本质上不是真正的泛型,而是利用了类型擦除(type erasure),比如下面的代码就会出现错误: 报的错误是:both methods have same erasure ...
- JAVA泛型中的类型擦除及为什么不支持泛型数组
一,数组的协变性(covariant array type)及集合的非协变性 设有Circle类和Square类继承自Shape类. 关于数组的协变性,看代码: public static doubl ...
- Java泛型中的类型擦除机制简单理解
Java的泛型是JDK1.5时引入的.下面只是简单的介绍,不做深入的分析. Java的泛型是伪泛型.为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首 ...
- 使用Java泛型返回动态类型
返回一个指定类型的集合,并且clazz必须继承IGeoLog对象或者是其本身 <T extends IGeoLog> List<T> getLogListSql(Class&l ...
- Java泛型总结---基本用法,类型限定,通配符,类型擦除
一.基本概念和用法 在Java语言处于还没有出现泛型的版本时,只能通过Object是所有类型的父类和类型强制转换两个特点的配合来实现类型泛化.例如在哈希表的存取中,JDK1.5之前使用HashMap的 ...
- Java泛型的逆变
在上篇<Java泛型的协变>这篇文章中遗留以下问题——协变不能解决将子类型添加到父类型的泛型列表中.本篇将用逆变来解决这个问题. 实验准备 我们首先增加以下方法,见代码清单1所示. 代码清 ...
随机推荐
- C#中的垃圾回收机制与delegate
在DeepStream的C#版本调试过程中,发现了一个问题,运行一段时间后,大概每次内存到16M(Debug模式)就会异常 错误“System.NullReferenceException:未将对象引 ...
- 你必须知道的10个提高Canvas性能技巧
你还在抱怨自己写的canvas demo徘徊在10帧以下吗?你还在烦恼打开自己写的应用就听见CUP风扇转吗?你正在写一个javascript Canvas库吗?那么下面九点就是你必须知道的! 一.预渲 ...
- c语言学习笔记---预编译
专题三: 1) 预编译 处理所有的注释,以空格代替, 将所有的#define删除,并且展开所有的宏定义, 处理条件编译指令#if,#ifdef,#elif,#else,#endif 处理# ...
- STL——序列式容器
一.容器概述与分类 1. STL容器即是将运用最广的一些数据结构实现出来.常用的数据结构有array, list, tree, stack, queue, hash table, set, map…… ...
- Onpaint和OnDraw的区别
(一) OnPaint 和 OnDraw (1)OnPaint是WM_PAINT消息的消息处理函数,在OnPaint中调用OnDraw,一般来说,用户自己的绘图代码应放在OnDraw中. (2)OnP ...
- SpringMVC实现多文件(批量)上传
1.springMVC实现多文件上传需要的包如图2.webroot下的结构如图所示 3.java代码: package cn.lxc.controller; import java.io.File; ...
- iOS添加自定义字体
字体有相应的字体文件,一般是以ttf或者otf为后缀,我们可以去一些第三方网站去下载(也有人专门做了字体出售),Google Fonts是个比较好的网站,可以去找找看.我们就用Open Sans这个字 ...
- windows 命令行下 简单好用的查看端口占用情况的方法
在windows命令行窗口下执行: C:\>netstat -aon|findstr "4444" TCP 127.0.0.1:4444 0.0.0.0:0 LISTENIN ...
- 【Linux】 解决报错: ImportError: libSM.so.6: cannot open shared object file: No such file or directory
centos7 + python3.6.4 我使用 pip3 install opencv-python 安装了opencv-python 之后,在使用 import cv2 报错如下 报错原因 ...
- 编译内核时出现__bad_udelay错误
今天编译内核时候遇到了__bad_udelay错误,然后编不过去了,仔细一看发现是udelay函数的参数太大,内核不允许延时这么多.于是换成了mdelay函数,以毫秒为单位延时,问题解决.