查看“核心技术:泛型”的源代码
←
核心技术:泛型
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:JavaCore]] == 为什么要使用泛型 == 泛型程序设计(Generic programming) 意味着编写的代码可以被很多不同类型的对象所重用。 类型参数( type parameters )。ArrayList 类有一个类型参数用来指示元素的类型: <syntaxhighlight lang="java"> ArrayList<String> files = new ArrayList<String>(); </syntaxhighlight> * 在Java SE 7 及以后的版本中, 构造函数中可以省略泛型类型: *: <syntaxhighlight lang="java"> ArrayList<String> files = new ArrayList<>(); </syntaxhighlight> == 定义简单泛型类 == 一个泛型类( generic class ) 就是具有一个或多个类型变量的类。 * 换句话说,泛型类可看作普通类的工厂。 == 泛型方法 == * 类型变量放在修饰符(这里是public static ) 的后面,返回类型的前面。 <syntaxhighlight lang="java"> class ArrayAlg { public static <T> T getMiddle(T... a) { return a[a.length / 2]; } } </syntaxhighlight> == 泛型变量的限定 == 是将T 限制为实现了Comparable 接口(只含一个方法compareTo 的标准接口)的类: <syntaxhighlight lang="java"> public static <T extends Coiparab1e> T min(T[] a) . . . </syntaxhighlight> * 使用关键字extends 而不是implements * T 和绑定类型可以是类, 也可以是接口 * 一个类型变量或通配符可以有多个限定: *: <syntaxhighlight lang="java"> T extends Comparable & Serializable </syntaxhighlight> *: 限定类型用“&”分隔,而逗号用来分隔类型变量。 == 泛型代码和虚拟机 == === 类型擦除 === 无论何时定义一个泛型类型, 都自动提供了一个相应的原始类型( raw type )。 * 原始类型的名字就是删去类型参数后的泛型类型名。 * 擦除(erased) 类型变量, 并替换为限定类型(无限定的变量用Object)。 如: <syntaxhighlight lang="java"> 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 newValue) { first = newValue; } public void setSecond(T newValue) { second = newValue; } } </syntaxhighlight> 擦除为: <syntaxhighlight lang="java"> public class Pair { private Object first; private Object second; public Pair() { first = null ; second = null ; } 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 newValue) { first = newValue; } public void setSecond(Object newValue) { second = newValue; } } </syntaxhighlight> * 原始类型用第一个限定的类型变量来替换, 如果没有给定限定就用Object 替换。 例: <syntaxhighlight lang="java"> 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; } } } </syntaxhighlight> 擦除为: <syntaxhighlight lang="java"> public class Interval implements Serializable { private Comparable lower; private Coiparable upper; ... public Interval (Coiparable first, Coiparable second) { . . . } } </syntaxhighlight> === 翻译泛型表达式 === 对于如下表达式: <syntaxhighlight lang="java"> Pair<Employee> buddies = . .; Employee buddy = buddies.getFirst(); </syntaxhighlight> 编译器把这个方法调用翻译为两条虚拟机指令: # 对原始方法Pair.getFirst 的调用。 # 将返回的Object 类型强制转换为Employee 类型。 === 翻译泛型方法 === 类型擦除也会出现在泛型方法中: <syntaxhighlight lang="java"> public static <T extends Comparable〉T min(T[] a) </syntaxhighlight> 擦除为: <syntaxhighlight lang="java"> public static Comparable min(Comparable[] a) </syntaxhighlight> 方法的擦除带来了两个复杂问题。如: <syntaxhighlight lang="java"> class Datelnterval extends Pair<LocalDate> { public void setSecond (Local Date second) { if (second.compareTo(getFi rst()) >= 0) super. setSecond (second); } ... } </syntaxhighlight> 这个类擦除后变成: <syntaxhighlight lang="java"> class Dateinterval extends Pair// after erasure { public void setSecond (Local Date second) { . . . } ... } </syntaxhighlight> 而Datelnterval同时存在一个从Pair继承的setSecond方法,即: <syntaxhighlight lang="java"> pub1ic void setSecond (Object second) </syntaxhighlight> 考虑下面的语句序列: <syntaxhighlight lang="java"> Datelnterval interval = new Datelnterval (...) ; Pair<LocalDate> pair= interval; // OK--assignment to superclass pair.setSecond (aDate); </syntaxhighlight> 在这里,'''类型擦除与多态发生了冲突。'''要解决这个问题,就需要'''编译器在Datelnterval类中生成一个桥方法(bridgemethod)''': <syntaxhighlight lang="java"> public void setSecond(Object second) { setSecond((Date) second); } </syntaxhighlight> 有关Java 泛型转换的事实: * '''虚拟机中没有泛型, 只有普通的类和方法'''。 * '''所有的类型参数都用它们的限定类型替换'''。 * '''桥方法被合成来保持多态'''。 * '''为保持类型安全性,必要时插人强制类型转换'''。 === 调用遗留代码 === == 约束与局限性 == == 泛型类的继承规则 == == 通配符类型 == == 反射和泛型 ==
返回至“
核心技术:泛型
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息