java编程之泛型(三)
来源:互联网 发布:蚕丝被淘宝评价 编辑:程序博客网 时间:2024/06/05 01:03
第五部分 通配符
1、协变
//注:以下示例使用的同名类,均来自于此class A{}class B extends A{}class C extends B{}class D extends A{}
首先,让我们来了解一下协变(covariant)的概念
数组是协变的:
public class CovariantArray{ public static void main(String[] args){ A[] a = new B[]; a[0] = new B(); a[1] = new C(); //a[3] = new D(); //抛出ArrayStoreException异常 }}
在这段程序的main函数下的第一行创建一个B数组,并将其复制给它的基类F的数组引用,这样做是允许的,因为B也是一种A类型,因此B数组也是一种A数组,这叫做数组的协变性 但要明确的是,运行时的类型却是B[],因此你也只能在这个数组当中放入B类型或B的导出类型。
泛型不是协变的:
对于上述的A类和B类,`List<B>` 不是 `List<A>` 的子类型,试图在要求 `List<A>` 的位置提供 `List<B>` 是一个类型错误.那么我们该如何实现泛型的向上转型呢?这时候通配符就起到了作用:
2、上边界限定通配符
通配符在泛型系统中的作用部分来自其不会发生协变这一特性。为了完成向上转型这一动作,我们可以采用通配符来解决。
先看一个例子:
public class GenericsAndConvariance{ public static void main(String[] args){ //通配符使用一个问号表示类型参数,是一种表示未知类型的类型约束的方法。 List<? extends A> example = Arrays.asList(new B()); example.add(null); example.contains(new B()); example.indexOf(new B()); B b = (B)example.get(0); //如果执行下面的代码将会报错 //违反类型安全限制 //example.add(new B()); //example.add(new A()); }}
看起来,`List<? extends A>`似乎意味着这个List可以持有任何类型的A,但实际情况并不是这样。此时的example已经不是原始的List对象,而是指定为`List<? extends A>`的对象,而它的add(),其参数也变为“? extends A”。 虽然编译器知道这一定是一个A的子类,A是它的上边界,可是它并不明确这里具体需要A的哪个子类,出于类型的安全限制,因此它不会接受任何类型的A.例如例子中“B b = (B)example.get(0);”是合法的。 需要明确的是,如果调用某个返回 A 的方法,这是安全的。因为我们知道,在这个 List 中,不管它实际的类型到底是什么,但肯定能转型为 A,所以编译器允许返回 A。 但是我们注意到,example.add(null)却是可以执行的,这是因为 null 对任何引用类型而言是一个空值。 同时,example.contains(new A()); example.indexOf(new A()); 是可执行的。因为contains方法和indexOf方法的参数是Object,它不涉及任何通配符,因此它是安全的。
3、下边界通配符(超类型通配符)
超类型通配符:<? super ClassName>
或适用类型参数<? super T>
看下面的例子
public class SuperTypeWildcards { static void writeTo(List<? super B> a) { a.add(new B()); a.add(new C()); // apples.add(new A()); // 错误 }}
方法writeTo的参数类型是`List<? super B>`,它表示的是某种类型的List,我们虽然不知道这种类型具体是什么,但我们清楚它一定是B的父类,因此,向这个 List 添加一个 B 或者B的导出类型的对象是安全的,这些对象都可以向上转型为 B。 可是我们不知道加入 A 对象是否安全,因为那样会使得这个 List 添加跟 B 无关的类型。
4、无界通配符
无界通配符:<?>,如:List<?>。它没有任何限定,因此无界通配符似乎等价于使用原生类。 那么使用无界通配符和直接使用原生类究竟有什么区别呢? 例如,List<?> list 表示的是: list 是持有某种特定类型的 List,但是不知道具体是哪种类型。那么我们可以向其中添加对象吗?当然不可以,因为并不知道实际是哪种类型,所以不能添加任何类型,这不安全。 而 List list ,也就是没有泛型参数,表示这个 list 持有的元素的类型是 Object,因此可以添加任何类型的对象,只不过编译器会有警告信息。
0 0
- java编程之泛型(三)
- Java专题(三)之网络编程
- Java 并发编程之测试(三)
- Java 并发编程之测试(三)
- java socket编程之聊天室(三)
- Java之网络编程(三)TCP
- Java入门之编程基础(三)
- Java 并发编程 之 volatile(三)
- Java Socket编程之三
- 【java网络编程】之三
- java并发编程之三
- Java基础之(三十七)Java多线程编程<三>
- Java 并发编程之任务取消 (三)
- Java 并发编程之线程池的使用 (三)
- Java 并发编程之线程池的使用 (三)
- Java并发编程读书笔记(三)之发布与溢出
- java网络socket编程(三)之ServerSocket服务器端
- Java编程思想之每天两小时(三)
- 设备电量监测原理
- 第七届蓝桥杯C/C++省赛B组真题解析与答案
- 用java面向对象思想求三角形的面积和周长
- leetcode 53
- 设计模式之简单工厂模式(整理笔记)
- java编程之泛型(三)
- MFC编个对话框,能够实时显示摄像头捕捉的镜头
- 卷积滤波器如何提取图像特征
- 【p1162-填充颜色】解题记录
- 剑指offer-倒序打印链表
- Linux中有关磁盘空间的命令
- 电子版《邓小平文选》的出版前言
- 中文乱码问题
- Ubuntu下Android开发-手机识别