【JavaSE系列-基础篇6】——泛型类型

来源:互联网 发布:.net cms 源码 编辑:程序博客网 时间:2024/06/06 23:16

泛型类型是对类型进行参数化的泛型类或接口。接下来我们会修改box类来演示这一概念。

一个简单的Box类

首先检查对任何类型的对象进行操作的非泛型类。它只需要提供2个方法:向box添加对象的set方法,以及get方法。

public class Box {    private Object object;    public void set(Object object) { this.object = object; }    public Object get() { return object; }}

既然,它的方法接收或者返回一个object,你可以使用任何类型,只要它不是原始类型之一。这没有办法在编译时去校验。一部分代码可以放置一个Integer到box中,期望能够从中获取integers。然而另一方面,可能错误的防止了String类型,在运行时就会出错。

Box类的泛型版本

泛型类的定义格式:

class name<T1, T2, ..., Tn> { /* ... */ }

在类型参数部分,被<>分割,紧随着类名。它指定了类型参数 T1,T2……Tn.

更新的box类中使用了泛型,你通过修改代码“public class Box”为“public class Box< T>”来声明一个泛型类型。这个类型变量T可以在这个类中的任何地方使用。

修改后的Box类变成了这样:

/** * Generic version of the Box class. * @param <T> the type of the value being boxed */public class Box<T> {    // T stands for "Type"    private T t;    public void set(T t) { this.t = t; }    public T get() { return t; }}

如你所见,所有出现的object都被替换为了T,一个类型变量可以为你指定的任何非原始类型:任何类,接口类型,数组类型,甚至是类型变量。

相同的技术可以适用于创建泛型接口。

类型参数命名规范

按照惯例,类型参数是单个大写的字母。这和你已经知道的变量命名规范成为一个鲜明的对比,而且这样写的原因为:没有这个规范,将要很难区分类型变量和普通类,接口名字的不同。

最常见的类型参数名称为:

E - Element (used extensively by the Java Collections Framework)K - KeyN - NumberT - TypeV - ValueS,U,V etc. - 2nd, 3rd, 4th types

调用和实例化一个泛型类型

在你的代码中参考这个泛型类,你必须执行泛型类型调用,替换T为具体的值,例如Integer:

Box<Integer> integerBox;

你可以将泛型类型调用看做和普通方法调用类似,但是不是传递参数到一个方法,而是传递一个类型参数。在这个例子中的Integer。


类型参数,参数术语
许多程序员会将type parameter和type argument互换使用。但是他们是不一样的。当编码时,一个提供类型参数以创建一个参数化类型。然而,在Foo< T >中的T是一个类型参数,而Foo< String>中的String是一个具体的参数类型。使用这些术语时,本课程将会遵守此定义。


像其他的变量声明一样,代码不会创建一个新的Box对象。它只是声明integerBox将持有对“Box of Integer”的引用,这是如何读取Box < Integer>。
泛型类型的调用通常称为参数化类型。

为了实例化这个类,我们使用关键字new,像往常一样,但是在类名和括号之间放置< Integer>。

菱形语法

在JavaSE7或者更高版本,只要编译器可以确定,可以使用空的一组类型参数(<>)替换调用泛型类的构造函数所需的类型参数。这对尖角括号<>,被非正式地称为菱形。例如,您可以使用以下语句创建Box < Integer >的实例:

Box<Integer> integerBox = new Box<>();

多种类型参数

在前面提到的,泛型类可以有多种类型参数。例如,实现了泛型接口Pair的泛型类OrderdPair:

public interface Pair<K, V> {    public K getKey();    public V getValue();}public class OrderedPair<K, V> implements Pair<K, V> {    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类的实例:

Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);Pair<String, String>  p2 = new OrderedPair<String, String>("hello", "world");

代码 new OrderedPair< String, Integer >,将K实例化为String,将V实例化为Integer。因此,OrderedPair的构造函数的参数类型分别为String和Integer。由于自动装箱,将String和int传递给该类是有效的。

在菱形语法一章提到的,因为Java编译器可以通过OfderedPair< String,Integer>来推断k和v的类型,所以这些语句可以使用菱形符号来缩短:

OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);OrderedPair<String, String>  p2 = new OrderedPair<>("hello", "world");

创建泛型接口,和泛型类一样,使用同样的规范。

参数化类型

您也可以使用参数化类型(即List )替换类型参数(即K或V)。例如,使用OrderedPair

OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));
阅读全文
0 0
原创粉丝点击