泛型类型
泛型类型是通过类型参数化的泛型类或接口,修改以下Box类以演示此概念。
一个简单的Box类首先检查一个对任何类型的对象进行操作的非泛型Box类,它只需要提供两个方法:set,它将一个对象添加到box中,get,它将检索它:
public class Box { private Object object; public void set(Object object) { this.object = object; } public Object get() { return object; } }
由于它的方法接受或返回一个Object,所以你可以自由地传入任何你想要的东西,前提是它不是一种原始类型,无法在编译时没有办法验证如何使用该类,代码的一部分可能会在box中放置一个Integer并期望从中获取Integer,而代码的另一部分可能会错误地传入String,从而导致运行时错误。
Box类的泛型版本泛型类使用以下格式定义:
class name{ /* ... */ }
由尖括号(<>)分隔的类型参数部分跟在类名后面,它指定类型参数(也称为类型变量)T1, T2, ...和Tn。
要更新Box类以使用泛型,可以通过将代码“public class Box”更改为“public class Box
通过此更改,Box类变为:
/** * Generic version of the Box class. * @paramthe type of the value being boxed */ public class Box { // T stands for "Type" private T t; public void set(T t) { this.t = t; } public T get() { return t; } }
如你所见,所有出现的Object都被T替换,类型变量可以是你指定的任何非基本类型:任何类类型、任何接口类型、任何数组类型,甚至是其他类型变量。
可以应用相同的技术来创建泛型接口。
类型参数命名约定按照惯例,类型参数名称是单个大写字母,这与你已经了解的变量命名约定形成鲜明对比,并且有充分的理由:如果没有这种约定,就很难区分类型变量和普通类或接口名称。
最常用的类型参数名称是:
E — 元素(Java集合框架广泛使用)
K — 键
N — 数
T — 类型
V — 值
S、U、V等 — 第二、第三、第四种类型
你将在整个Java SE API和本课程的其余部分中看到这些名称。
调用和实例化泛型类型要从代码中引用泛型Box类,必须执行泛型类型调用,它将T替换为某些具体值,例如Integer:
BoxintegerBox;
你可以将泛型类型调用视为与普通方法调用类似,但不是将参数传递给方法,而是将类型参数(在本例中为Integer)传递给Box类本身。
类型参数和类型参数术语:许多开发人员互换地使用术语“类型参数”和“类型实参”,但这些术语并不相同,编码时,提供类型实参以创建参数化类型,因此,Foo中的T是类型参数,而Foo f 中的String是类型实参,本课程在使用这些术语时会遵循此定义。
与任何其他变量声明一样,此代码实际上并不创建新的Box对象,它只是声明integerBox将保存对“Box of Integer”的引用,这就是Box
泛型类型的调用通常称为参数化类型。
要实例化此类,请像往常一样使用new关键字,但在类名和括号之间放置
Box菱形integerBox = new Box ();
在Java SE 7及更高版本中,只要编译器可以从上下文中确定或推断类型参数,就可以用一组空的类型参数(<>)替换调用泛型类的构造函数所需的类型参数,这对尖括号<>非正式地称为菱形,例如,你可以使用以下语句创建Box
BoxintegerBox = new Box<>();
有关菱形表示法和类型推断的更多信息,请参阅类型推断。
多个类型参数如前所述,泛型类可以有多个类型参数,例如,OrderedPair泛型类,它实现了Pair泛型接口:
public interface Pair{ public K getKey(); public V getValue(); } public class OrderedPair implements Pair { private K key; private V value; public OrderedPair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } }
以下语句创建OrderedPair类的两个实例:
Pairp1 = new OrderedPair ("Even", 8); Pair p2 = new OrderedPair ("hello", "world");
代码new OrderedPair
正如菱形中所提到的,因为Java编译器可以从声明OrderedPair
OrderedPairp1 = new OrderedPair<>("Even", 8); OrderedPair p2 = new OrderedPair<>("hello", "world");
要创建泛型接口,请遵循与创建泛型类相同的约定。
参数化类型你还可以使用参数化类型(即List
OrderedPair上一篇:为什么要使用泛型? 下一篇:泛型原始类型> p = new OrderedPair<>("primes", new Box (...));
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/72926.html
Java™ 教程 Java教程是为JDK 8编写的,本页面中描述的示例和实践没有利用在后续版本中引入的改进。 Java教程是希望使用Java编程语言创建应用程序的程序员的实用指南,其中包括数百个完整的工作示例和数十个课程,相关课程组被组织成教程。 覆盖基础知识的路径 这些教程以书籍的形式提供,如Java教程,第六版,前往Amazon.com购买。 入门 介绍Java技术和安装Java开发软件并使用...
类型推断 类型推断是Java编译器查看每个方法调用和相应声明的能力,以确定使调用适用的类型参数,推理算法确定参数的类型,如果可用,还确定分配或返回结果的类型,最后,推理算法尝试查找适用于所有参数的最具体类型。 为了说明最后一点,在下面的示例中,推断确定传递给pick方法的第二个参数是Serializable类型: static T pick(T a1, T a2) { return a2; } ...
泛型原始类型 原始类型是没有任何类型参数的泛型类或接口的名称,例如,给定Box泛型类: public class Box { public void set(T t) { /* ... */ } // ... } 要创建参数化类型的Box,请为形式类型参数T提供实际类型参数: Box intBox = new Box(); 如果省略实际的类型参数,则创建一个原始类型Box: Box...
泛型 在任何重要的软件项目中,bug都是不可避免的,仔细的规划、编程和测试可以帮助减少它们的普遍性,但是它们总会在某个地方以某种方式潜入你的代码,随着新功能的引入以及你的代码库在规模和复杂性方面的增长,这一点变得尤为明显。 幸运的是,一些错误比其他错误更容易被发现,例如,编译时错误可以在早期检测到,你可以使用编译器的错误消息来确定问题所在并立即修复它。但是,运行时错误可能会更成问题,它们并不总是立...
泛型方法 泛型方法是引入其自己的类型参数的方法,这类似于声明泛型类型,但类型参数的范围仅限于声明它的方法,允许使用静态和非静态泛型方法,以及泛型类构造函数。 泛型方法的语法包括类型参数列表,在尖括号内,它出现在方法的返回类型之前,对于静态泛型方法,类型参数部分必须出现在方法的返回类型之前。 Util类包含一个泛型方法compare,它比较两个Pair对象: public class Util { ...
阅读 979·2021-11-25 09:43
阅读 1648·2019-08-30 13:59
阅读 1507·2019-08-30 11:22
阅读 2101·2019-08-30 11:06
阅读 1280·2019-08-28 17:51
阅读 3626·2019-08-26 12:12
阅读 764·2019-08-26 12:11
阅读 426·2019-08-26 12:10