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所示. 代码清 ...
随机推荐
- React Native(五)——获取设备信息react-native-device-info
心酸史: 自从接触rn开始后,越来越多的引入第三方组件而开始的配置文件,让自己一再头疼: 明明是按照官方文档一步一步的配置,为什么别人可以做到的自己却屡屡出错,真是哭笑不得--从微信分享react-n ...
- 用layer插件实现tp3.2的分页
主要需要用到 /layer/layer.js 这个, 现在一个tp前端视图/article/index.html <!DOCTYPE html> <html lang=" ...
- junit4 详解
转:http://www.cnblogs.com/eggbucket/archive/2012/02/02/2335697.html JUnit4概述 JUnit4是JUnit框架有史以来的最大改进, ...
- 部署OpenStack问题汇总(一)--使用packstack安装openstack:源问题的处理
在安装的过程中,遇到了源的问题,找不到包的网页: 重新打开 预装源地址,打开epel-openstack-havana.repo 文件,显示如下: # Place this file in yo ...
- Sublime text3配置LiveReload 浏览器即时刷新
1.在sublime控件台 install livereload插件(缺点:每次重新打开Sublime都需要启动) 2.配置Preference > Package Settings > ...
- 编译源码 JAVA out of memory
- zabbix配置server,proxy,agent架构
author: headsen chen date:2018-10-30 19:49:50 环境: centos 6.8_x86_64 zabbix-server: 192.168.1.130 z ...
- C语言常用基础位操作
1.使用下面的代码将最右边的1改变为0,假如没有1则结果为0(e.g.,01011000=>01010000): x & (x-1) 此代码可以用来判断一个无符号的整数是否为2的幂,假 ...
- SIM900A基站定位调试笔记 -转
第1步:ATE1 握手并设置回显 第2步:AT+CGMR 查看SIM900的版本信号 第3步:AT+CSQ 查看信号质量 第4步:AT+CREG? 查看GSM是否注册成功 第5步:AT+CGREG? ...
- dhroid - DhNet 网络http工具
extends:http://www.eoeandroid.com/thread-327440-1-1.html DhNet net=new DhNet("路劲"); ne ...