Java理论与实践: 操纵通配符简化泛型操纵[Java编程]
本文“Java理论与实践: 操纵通配符简化泛型操纵[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
自从泛型被增添到 JDK 5 语言以来,它一向都是一个颇具争议的话题.一部 分人认为泛型简化了编程,扩大了范例系统从而使编译器可以查验范例安全;另 外一些人认为泛型增添了很多不必要的复杂性.关于泛型我们都阅历过一些痛楚 的回想,但毫无疑问通配符是最棘手的部份.
通配符基本介绍
泛型是一种表示类或办法行为关于未知范例的范例约束的办法,比方 “不管 这个办法的参数 x 和 y 是哪类范例,它们必须是相同的范例”,“必须为这些 办法供应同一范例的参数” 大概 “foo() 的返回值和 bar() 的参数是同一类 型的”.
通配符 — 利用一个奇特的问号表示范例参数 — 是一种表示未知范例的类 型约束的办法.通配符并不包含在最初的泛型计划中(发源于 Generic Java (GJ)项目),从形成 JSR 14 到公布其终究版本之间的五年多时间内完成计划 历程并被增添到了泛型中.
通配符在范例系统中具有重要的意义,它们为一个泛型类所指定的范例调集 供应了一个有效的范例范围.对泛型类 ArrayList 而言,关于肆意(引用)类 型 T,ArrayList<?> 范例是 ArrayList<T> 的超范例(近似原始 范例 ArrayList 和根范例 Object,但是这些超范例在履行范例推断方面不是很 有效).
通配符范例 List<?> 与原始范例 List 和具体范例 List<Object> 都不相同.假如说变量 x 具有 List<?> 范例,这 表示存在一些 T 范例,此中 x 是 List<T>范例,x 具有相同的构造,尽 管我们不知道其元素的具体范例.这并不表示它可以具有肆意内容,而是指我们 并不理解内容的范例限制是什么 — 但我们知道存在 某种限制.另一方面,原 始范例 List 是异构的,我们不能对其元素有任何范例限制,具体范例 List<Object> 表示我们明确地知道它能包含任何对象(当然,泛型的类 型系统没有 “列表内容” 的概念,但可以从 List 之类的调集范例轻松地理解 泛型).
通配符在范例系统中的作用部份来自其不会发生协变(covariant)这一特点 .数组是协变的,因为 Integer 是 Number 的子范例,数组范例 Integer[] 是 Number[] 的子范例,因此在任何需求 Number[] 值的地方都可以供应一个 Integer[] 值.另一方面,泛型不是协变的, List<Integer> 不是 List<Number> 的子范例,试图在要求 List<Number> 的位置供应 List<Integer> 是一个范例错误.这不算很严重的问题 — 也不是全部人 都认为的错误 — 但泛型和数组的差别行为的确惹起了很多混乱.
我已利用了一个通配符 — 接下来呢?
清单 1 展示了一个简单的容器(container)范例 Box,它支持 put 和 get 操作. Box 由范例参数 T 参数化,该参数表示 Box 内容的范例, Box<String> 只能包含 String 范例的元素.
清单 1. 简单的泛型 Box 范例
public interface Box<T> {
public T get();
public void put(T element);
}
通配符的一个好处是答应编写可以操作泛型范例变量的代码,并且不需求了 解其具体范例.比方,假定有一个 Box<?> 范例的变量,比方清单 2 unbox() 办法中的 box 参数.unbox() 若何处理已传送的 box?
清单 2. 带有通配符参数的 Unbox 办法
public void unbox(Box<?> box) {
System.out.println(box.get());
}
事实证明 Unbox 办法能做很多工作:它能调用 get() 办法,并且能调用任 何从 Object 担当而来的办法(比方 hashCode()).它惟一不能做的事是调用 put() 办法,这是因为在不知道该 Box 实例的范例参数 T 的情形下它不能查验 这个操作的安全性.由于 box 是一个 Box<?> 而不是一个原始的 Box, 编译器知道存在一些 T 充当 box 的范例参数,但由于不知道 T 具体是什么, 您不能调用 put() 因为不能查验这么做不会违反 Box 的范例安全限制(实际上 ,您可以在一个特别的情形下调用 put():当您传送 null 字母时.我们大概不 知道 T 范例代表什么,但我们知道 null 字母对任何引用范例而言是一个空值 ).
关于 box.get() 的返回范例,unbox() 理解哪些内容呢?它知道 box.get() 是某些未知 T 的 T,因此它可以推断出 get() 的返回范例是 T 的擦除 (erasure),关于一个无上限的通配符就是 Object.因此清单 2 中的表达式 box.get() 具有 Object 范例.
以上是“Java理论与实践: 操纵通配符简化泛型操纵[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |