JavaSE笔记之<泛型再理解(简化版)>
来源:互联网 发布:windows音量图标不见了 编辑:程序博客网 时间:2024/05/16 07:39
java中有类(class)、方法(method)、域(field) 、接口 它们都能使用泛型,但域的泛型要和类关联(且除了静态数据成员以外,因为它不和实例相关联,泛型类是和实例相关联的)。
简单介绍下泛型的一些基本术语,以ArrayList<E>和ArrayList<Integer>做简要介绍:
整个成为ArrayList<E>泛型类型
ArrayList<E>中的 E称为类型变量或者类型参数
class Generic<E>{}中的E称为泛型参数
整个ArrayList<Integer> 称为参数化的类型
ArrayList<Integer>中的integer称为类型参数的实例或者实际类型参数
·ArrayList<Integer>中的<Integer>念为typeof Integer
ArrayList称为原始类型
①边界
边界是类型参数的一种限制条件(约束),一般都是限制某个参数为某个类型的子集(定义的时候),为了执行这种限制,java泛型重用了extends关键字。
1、不管该限定是类还是接口,统一都使用关键字 extends,泛型参数不能给出超类型边界(即super)
如class CanineHero <P extends superHearing & SuperMell>
extends后面是一个确切类型
自限定:Class Generic <T extends Generic<T>>{} Generic<T>相当于Generic<String>是一个参数类型为T的类型,是T的边界
②通配符
List<?> 包含的是任意类型的List(无界通配符)
List<? extends Number>包含的是Number或者其子类的List(上界通配符)
List<? super Integer> 包含的是Integer或者其父类的List(逆变,下界通配符)
这个其实已经是指定了类型参数了,指定类型参数包括两种,一是直接确定类型参数;而是用通配符。因此可以是List<String>或者List<?>这样
③泛型擦除
由于java和C++实现泛型方式不一样,java是code share的方式,即只有一个字节码对应多种不同的类型。实现此方式需要用到泛型擦除,这是java实现泛型的底层原理。
如何擦除?
1.将所有的泛型参数用其最左边界类型(限定类型)替换。<T>等同于<T extends Object>即T会用Object代替
2.移除所有的类型参数。
class Collections { public static <A extends Comparable<A>>A max(Collection <A> xs) { //<>中的A不用管,只有定义的时候方法前面的是泛型参数,方法内部的是类型参数 Iterator <A> xi = xs.iterator(); A w = xi.next(); while (xi.hasNext()) { A x = xi.next(); if (w.compareTo(x) < 0) w = x; } return w; } }
类型擦除后:
class Collections { public static Comparable max(Collection xs) { Iterator xi = xs.iterator(); Comparable w = (Comparable) xi.next(); while (xi.hasNext()) { Comparable x = (Comparable) xi.next(); if (w.compareTo(x) < 0) w = x; } return w; } }
首先A被Comparable<A>代替 静态方法内部不用管,则A w = xi.next(); 类型擦除后变成Comparable<A> w = xi.next();
第二步移除所有的类型参数 Comparable<A> w = xi.next(); 变成 Comparable w = xi.next();
④类型擦除引起的问题及解决方法
先检查,再编译。检查针对的是引用。
既然说类型变量会在编译的时候擦除掉,那为什么我们往ArrayList<String> arrayList=new ArrayList<String>();所创建的数组列表arrayList中,不能使用add方法添加整形呢?不是说泛型变量Integer会在编译时候擦除变为原始类型Object吗,为什么不能存别的类型呢?既然类型擦除了,如何保证我们只能使用泛型变量限定的类型呢?
java是如何解决这个问题的呢?java编译器是通过先检查代码中泛型的类型,然后再进行类型擦除,再进行编译的。
public static void main(String[] args) { ArrayList<String> arrayList=new ArrayList<String>(); arrayList.add("123"); arrayList.add(123);//编译错误 }因为arrayList是ArrayList<String>类型的引用,编译器会查看上下文,检查到第三行arrayList.add(123)时,由于其中加的是整型数据,所以自动报错。
接着会编译。
部分参考:http://blog.csdn.net/lonelyroamer/article/details/7868820
- JavaSE笔记之<泛型再理解(简化版)>
- JavaSE笔记之<继承深入理解>
- JavaSE笔记之<多态深入理解>
- javaSE之接口理解
- JavaSE学习笔记之Annotation(注解)
- 学习笔记之JavaSE(38)--泛型
- 简化理解之:关键字synchronize
- JavaSE笔记之<final关键字>
- javaSE学习笔记之数据类型
- JavaSE笔记之<正则表达式>
- javaSE学习笔记之反射
- javaSE学习笔记之IO
- javaSE学习笔记之集合
- javaSE学习笔记之线程
- JavaSE初学笔记之<多线程>
- JAVASE学习笔记之集合
- JavaSE学习笔记之-----数组
- JavaSE学习笔记之-----集合
- 贪吃蛇小游戏java实现代码分析
- impdp时报错ORA-39083&ORA-01917
- Ubuntu下LAMP环境搭建
- Android 应用添加菜单
- ubuntu用户添加adduser, useradd (http://blog.csdn.net/lele52141/article/details/6593840)
- JavaSE笔记之<泛型再理解(简化版)>
- 能量英语(一)之激情英语
- java学习09--选择结构-switch练习、if和Switch使用比较
- 嵌入式入门
- TinyAdmin前端展现框架
- 多线程同步方法
- ThinkPHP RBAC功能小结
- Android Dalvik虚拟机初识
- WebView缓存图片的获取