泛型通配符使用指南
学习使用泛型编程时更困惑的一个方面是确定何时使用上界通配符以及何时使用下界通配符,此页面提供了设计代码时要遵循的一些准则。
对于本文的讨论,将变量看作提供的两个功能之一是有帮助的:
一个“In”变量
“in”变量向代码提供数据,想象一下带有两个参数的复制方法:copy(src, dest),src参数提供要复制的数据,因此它是“in”参数。
一个“Out”变量
“out”变量保存数据以供其他地方使用,在复制示例中,copy(src, dest),dest参数接受数据,因此它是“out”参数。
当然,一些变量既用于“in”又用于“out”目的 — 该场景也在指南中解决。
在决定是否使用通配符以及适合使用哪种类型的通配符时,可以使用“in”和“out”原则,以下列表提供了遵循的准则:
使用extends关键字定义带有上界通配符的“in”变量。
使用super关键字定义带有下界通配符的“out”变量。
在可以使用Object类中定义的方法访问“in”变量的情况下,使用无界通配符。
在代码需要作为“in”和“out”变量访问变量的情况下,不要使用通配符。
这些指南不适用于方法的返回类型,应该避免使用通配符作为返回类型,因为它强制程序员使用代码来处理通配符。
由List extends ...>定义的列表可以非正式地认为是只读的,但这不是一个严格的保证,假设你有以下两个类:
class NaturalNumber { private int i; public NaturalNumber(int i) { this.i = i; } // ... } class EvenNumber extends NaturalNumber { public EvenNumber(int i) { super(i); } // ... }
考虑以下代码:
Listle = new ArrayList<>(); List extends NaturalNumber> ln = le; ln.add(new NaturalNumber(35)); // compile-time error
因为List
你可以添加null。
你可以调用clear。
你可以获取迭代器并调用remove。
你可以捕获通配符并写入从列表中读取的元素。
你可以看到List extends NaturalNumber>定义的列表在严格意义上不是只读的,但你可能会这样想,因为你无法存储新元素或更改列表中的现有元素。
上一篇:泛型通配符捕获和Helper方法 下一篇:类型擦除文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/72941.html
Java™ 教程 Java教程是为JDK 8编写的,本页面中描述的示例和实践没有利用在后续版本中引入的改进。 Java教程是希望使用Java编程语言创建应用程序的程序员的实用指南,其中包括数百个完整的工作示例和数十个课程,相关课程组被组织成教程。 覆盖基础知识的路径 这些教程以书籍的形式提供,如Java教程,第六版,前往Amazon.com购买。 入门 介绍Java技术和安装Java开发软件并使用...
泛型通配符 在泛型代码中,称为通配符的问号(?)表示未知类型,通配符可用于各种情况:作为参数、字段或局部变量的类型,有时作为返回类型(尽管更好的编程实践是更加具体),通配符从不用作泛型方法调用、泛型类实例创建或超类型的类型参数。 以下部分更详细地讨论通配符,包括上界通配符、下界通配符和通配符捕获。 上界通配符 你可以使用上界通配符来放宽对变量的限制,例如,假设你要编写一个适用于List、List和...
泛型通配符捕获和Helper方法 在某些情况下,编译器会推断出通配符的类型,例如,列表可以定义为List,但是在评估表达式时,编译器会从代码中推断出特定类型,此场景称为通配符捕获。 在大多数情况下,你不必担心通配符捕获,除非你看到包含短语capture of的错误消息。 WildcardError示例在编译时产生捕获错误: import java.util.List; public class ...
泛型的限制 要有效地使用Java泛型,必须考虑以下限制: 无法使用基元类型实例化泛型类型 无法创建类型参数的实例 无法声明类型为类型参数的静态字段 无法对参数化类型使用强制类型转换或instanceof 无法创建参数化类型的数组 无法创建、捕获或抛出参数化类型的对象 无法重载将每个重载的形式参数类型擦除为相同原始类型的方法 无法使用基元类型实例化泛型类型 考虑以下参数化类型: class P...
泛型、继承和子类型 如你所知,只要类型兼容,就可以将一种类型的对象分配给另一种类型的对象,例如,你可以将Integer分配给Object,因为Object是Integer的超类型之一: Object someObject = new Object(); Integer someInteger = new Integer(10); someObject = someInteger; // OK ...
阅读 1482·2021-11-22 09:34
阅读 1636·2019-08-29 16:36
阅读 2627·2019-08-29 15:43
阅读 3072·2019-08-29 13:57
阅读 1268·2019-08-28 18:05
阅读 1853·2019-08-26 18:26
阅读 3212·2019-08-26 10:39
阅读 3348·2019-08-23 18:40