第12章 泛型程序设计
来源:互联网 发布:什么动物知天下事 编辑:程序博客网 时间:2024/06/05 03:50
1.为什么要使用泛型
泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。
在Java增加泛型类之前,泛型程序设计使用继承实现的。
2.定义简单泛型类
public class Pair<T>{ private T first; private T second; public Pair(){ first=null;second=null;} public Pair(T first,T second){ this.first=first;this.second=second;} public T getFirst(){ return first;} public T getSecond(){ return second;} public void setFirst(T first){ this.first=first;} public void setSecond(T second){ this.second=second;}}
3.泛型方法
class ArrayAlg{ public static <T> T getMiddle(T... a){ return a[a.length/2]; }}
4.类型变量的限定
有时,类或方法需要对类型变量加以约束。例:
class ArrayAlg{public static <T> T min(T[] a){if(a==null||a.length==0) return null;T smallest=a[0];for (int i=1;i<a.length;i++) {if (smallest.compareTo(a[i])>0) smallest=a[i];}return smallest;}}变量smallest类型为T,怎么才能确信T所属的类有compareT方法呢?解决这个问题的方案是将T限制为实现了Comparable接口的类
public static <T extends Comparable> T min(T[] a)...
<T extends BoundingType>表示T应该是绑定类型的子类型。T和绑定类可以是类,也可以是接口。
多个限定:T extends Comparable & Serializable
5.泛型代码和虚拟机
虚拟机中没有泛型类型对象,所有对象都属于普通类。无论何时定义了一个泛型类型,都自动提供了一个相应的原始类型,原始类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定的变量用Object)。Pair<T>的原始类型:
public class Pair{private Object first;private Object second;public Pair(Object first,Object second){this.first=first;this.second=second;}public Object getFirst(){ return first; }public Object getSecond(){ return second; }public void setFirst(Object first){ this.first=first; }public void setSecond(Object second){ this.second=second; }}原始类型用第一个限定的类型变量来替换。
public class Interval<T extends Comparable & Serializable> implements Serializable{private T lower;private T upper;...public Interval(T first,T second){if (first.compareTo(second)<=0) {lower=first;upper=second;}else{lower=second;upper=first;}}原始类型:
public class Interval implements Serializable{private Comparable lower;private Comparable upper;...public Interval(Comparable first,Comparable second){ ... }}如果切换限定,原始类型用Serializable替换T,编译器必须要向Comparable插入强制类型转换。为了提高效率,应该将标签接口(没有方法的接口)放在边界列表的末尾。
5.1 翻译泛型表达式
(1)调用原始方法
(2)将返回的Object对象进行强制类型转换
5.2 翻译泛型方法
//泛型方法public static <T extends Comparable> T min(T[] a)//擦除类型后的方法public static Comparable min(Comparable[] a)
示例:
class DateInterval extends Pair<Date>{public void setSecond(Date second){if(second.compareTo(getFirst())>=0)super.setSecond(second);}...}这个类擦除后变成
class DateInterval extends Pair{ //after erasurepublic void setSecond(Date second){ ... }...}存在另一个从Pair继承的setSecond方法,它有一个不同类型的参数Object
public void setSecond(Object second)考虑下面的程序:
DateInterval interval=new DateInterval(...);Pair<Date> pair=interval;//OK--assignment to superclasspair.setSecond(aDate);这里希望对setSecond的调用具有多态性,并调用最合适的那个方法。由于pair引用DateInterval对象,就应该调用DateInterval.setSecond。问题在于类型擦除与多态发生了冲突。为解决这个问题,编译器在DateInterval类中生成了一个桥方法。
public void setSecond(Object second){ setSecond((Date) second); }
Java泛型转换的事实:
·虚拟机中没有泛型,只有普通的类和方法
·所有的类型参数都用它们的限定类型替换
·桥方法被合成来保持多态
·为保持类型安全性,必要时插入强制类型转换
6.约束与局限性
(1)不能用基本类型实例化类型参数
(2)运行时类型检查只适用于原始类型 instanceof getClass方法 强制类型转换得到的都是原始类型
(3)不能创建参数化类型的数组 可以使用ArrayList
(4)Varargs警告
(5)不能实例化类型变量 不能使用new T(...),new T[...]或T.class这样的表达式
(6)泛型类的静态上下文中的类型变量无效 不能在静态域或方法中引用类型变量
(7)不能抛出或捕获泛型类的实例
(8)注意擦除后的冲突
7.泛型类型的继承规则
Pair<Manager>不是Pair<Employee>的一个子类
8.通配符类型
public static void printBuddies(Pair<Employee> p){Employee first=p.getFirst();Employee second=p.getSecond();System.out.println(first.getName()+" and "+second.getName()+" are buddies.");}
不能将Pair<Manager>传递给这个方法,解决方法:使用通配符类型。public static void printBuddies(Pair<? extends Employee> p)Pair<? extends Employee>的方法:
? extends Employee getFirst()void setFirst(? extends Employee)这样将不能调用setFirst方法,编译器只知道需要某个Employee的子类型,但不知道是什么类型。它拒绝传递任何特定的类型,毕竟?不能用来匹配。
8.1 通配符的超类型限定
? super Manager这个通配符限制为Manager的所有超类型。带有超类型限定的通配符可以为方法提供参数,但不能使用返回值。例:
? super Manager getFirst()void setFirst(? super Manager)编译器不知道setFirst的确切类型,但是可以使用任意Manager对象(或子类型)调用它,不能用Employee。如果调用getFirst,返回的对象类型不会得到保证,只能赋给Object。
9.反射和泛型
阅读全文
0 0
- 第12章 泛型程序设计
- 2015 7 7 Java核心技术卷一 第12章 泛型程序设计
- [Linux程序设计笔记]第12章:管道
- 《Java7程序设计》第12章 泛型
- 第1章 程序设计基础
- 《Windows程序设计》第4章
- 第4章汇编语言程序设计
- 《Windows程序设计》第5章
- 第3章 程序设计初步
- 第8章 通用程序设计
- 第1章 程序设计入门
- 第8章 通用程序设计
- 第01章 程序设计入门
- 第1章 程序设计入门
- 第8章 通用程序设计
- 第1章 程序设计入门
- 第2章 基本程序设计
- 第13章-Swing程序设计
- Java遍历集合、数组的四种方法
- 【面试】包装类型和字符串
- /UVA753APlugForUNIX
- 更多的结构化命令
- 开发中常见的路径的问题
- 第12章 泛型程序设计
- 1016. Phone Bills (25)
- 【Mybatis从0到1-008】MyBatis之映射文件(输入映射、输出映射)
- 利用C#进行socket编程(模拟服务器和客户端通信)
- XSD文件与XML文件有什么关系
- 读<参与感>
- Android学习心得(二) 关于getContext()
- Linux文件权限查看及修改命令chmod
- 深入Spring Boot:ClassLoader的继承关系和影响