# 泛型类型 > 原文: [https://docs.oracle.com/javase/tutorial/java/generics/types.html](https://docs.oracle.com/javase/tutorial/java/generics/types.html) *泛型类型*是通过类型参数化的泛型类或接口。以下`Box`类将被修改以演示该概念。 ## 一个简单的盒子类 首先检查对任何类型的对象进行操作的非泛型`Box`类。它只需要提供两种方法:`设置`,它将一个对象添加到框中,`获取`,它检索它: ```java public class Box { private Object object; public void set(Object object) { this.object = object; } public Object get() { return object; } } ``` 由于它的方法接受或返回`对象`,所以只要它不是原始类型之一,您就可以随意传入任何内容。在编译时无法验证类的使用方式。代码的一部分可能会在框中放置`Integer`并期望从中获取`Integer` ,而代码的另一部分可能错误地传入`String` ,导致运行时错误。 ## Box 类的通用版本 *泛型类*使用以下格式定义: ```java class name { /* ... */ } ``` 由尖括号(`<>` )分隔的类型参数部分遵循类名。它指定*类型参数*(也称为*类型变量*) `T1` , `T2` ,......和`Tn` ]。 要更新`Box`类以使用泛型,您可以通过将代码“ `public class Box` ”更改为“ `public class Box<”来创建*泛型类型声明 _ ; T>` “。这引入了类型变量`T` ,可以在类中的任何地方使用。 通过此更改, `Box`类变为: ```java /** * Generic version of the Box class. * @param the 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; } } ``` 如您所见,`对象`的所有出现都被`T`取代。类型变量可以是您指定的任何**非原始**类型:任何类类型,任何接口类型,任何数组类型,甚至是其他类型变量。 可以应用相同的技术来创建通用接口。 ## 键入参数命名约定 按照惯例,类型参数名称是单个大写字母。这与你已经知道的变量[命名](../nutsandbolts/variables.html#naming)约定形成鲜明对比,并且有充分的理由:如果没有这种约定,很难区分类型变量和普通类或接口名称之间的区别。 最常用的类型参数名称是: * E - Element(Java Collections Framework 广泛使用) * K - 钥匙 * N - 数字 * T 型 * V - 价值 * S,U,V 等 - 第 2,第 3,第 4 类型 您将在整个 Java SE API 和本课程的其余部分中看到这些名称。 要从代码中引用通用`Box`类,必须执行*泛型类型调用*,它将`T`替换为某些具体值,例如`整数`: ```java Box integerBox; ``` 您可以将泛型类型调用视为与普通方法调用类似,但不是将参数传递给方法,而是在这种情况下传递*类型参数 _ - `Integer` - 到`Box`类本身。 * * * **Type Parameter and Type Argument Terminology:** Many developers use the terms "type parameter" and "type argument" interchangeably, but these terms are not the same. When coding, one provides type arguments in order to create a parameterized type. Therefore, the `T` in `Foo` is a type parameter and the `String` in `Foo f` is a type argument. This lesson observes this definition when using these terms. * * * 与任何其他变量声明一样,此代码实际上不会创建新的`Box`对象。它简单地声明`integerBox`将保持对`Integer`的“ `Box` ”的引用,这是`Box< Integer>`被阅读。 泛型类型的调用通常称为*参数化类型*。 要实例化此类,像往常一样使用`new`关键字,但放置`< Integer>类名和括号之间的`: ```java Box integerBox = new Box(); ``` 在 Java SE 7 及更高版本中,只要编译器可以确定或推断类型参数,就可以用一组空的类型参数(<>)替换调用泛型类的构造器所需的类型参数。上下文。这对尖括号<>非正式地称为*钻石*。例如,您可以创建`Box< Integer>的实例。` ,声明如下: ```java Box integerBox = new Box<>(); ``` 有关菱形表示法和类型推断的更多信息,请参见[类型推断](genTypeInference.html)。 如前所述,泛型类可以有多个类型参数。例如,通用`OrderedPair`类,它实现了通用`Pair`接口: ```java 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`类的两个实例: ```java Pair p1 = new OrderedPair("Even", 8); Pair p2 = new OrderedPair("hello", "world"); ``` 代码, `new OrderedPair< String,Integer>` ,将`K`实例化为`串`和`V`作为`整数`。因此, `OrderedPair`的构造器的参数类型分别是`String`和`Integer` 。由于[自动装箱](../data/autoboxing.html),将`字符串`和`int`传递给该类是有效的。 如 [The Diamond](#diamond) 中所述,因为 Java 编译器可以从声明`OrderedPair< String,Integer>中推断`K`和`V`类型。` ,这些陈述可以使用钻石符号缩短: ```java OrderedPair p1 = new OrderedPair<>("Even", 8); OrderedPair p2 = new OrderedPair<>("hello", "world"); ``` 要创建通用接口,请遵循与创建泛型类相同的约定。 ## 参数化类型 您还可以用参数化类型(即`List< String>` )替换类型参数(即`K`或`V` )。例如,使用`OrderedPair< K,V>`示例: ```java OrderedPair> p = new OrderedPair<>("primes", new Box(...)); ```