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

泛型类型是对类型进行参数化的泛型类或接口。接下来我们会修改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 - Key
N - Number
T - Type
V - Value
S,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
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值