Java泛型之擦拭法

java的虚拟机是没有泛型类型对象的,所有的对象都属于普通类。

Table of Contents

擦拭法

无论什么时候定义一个泛型,编译的时候都会自动的匹配一个相应的原始类。这个原始类名就是去掉类型参数后的泛型类型名。类型变量会被擦除,替换为限定类型,或Object(没有限定时)。

例如一个泛型类Pair如下:

class Pair<T>
{
    private T first;
    private T second;

    public Pair (T first, T second)
    {
        this.first = first;
        this.second = second;
    }

    public T getFirst()
    {
        return this.first;
    } 

    public T getSecond ()
    {
        return this.second;
    }

    public void setFirst (T first)
    {
        this.first = first;
    }

    public void setSecond (T second)
    {
        this.second = second;
    }
}

原始类型如下:

class Pair
{
    private Object first;
    private Object second;

    public Pair (Object first, Object second)
    {
        this.first = first;
        this.second = second;
    }

    public Object getFirst()
    {
        return this.first;
    } 

    public Object getSecond ()
    {
        return this.second;
    }

    public void setFirst (Object first)
    {
        this.first = first;
    }

    public void setSecond (Object second)
    {
        this.second = second;
    }
}

这里因为泛型类T是一个没有限定的变量,所以直接用Object替换。

使用泛型的时候,我们编写的代码也是编译器看到的代码:

Pair<String> p = new Pair<>("Hello", "world");
String first = p.getFirst();
String last = p.getLast();

而虚拟机执行的代码并没有泛型:

Pair p = new Pair("Hello", "world");
String first = (String) p.getFirst();
String last = (String) p.getLast();

所以,Java的泛型是由编译器在编译时实行的,编译器内部永远把所有类型T视为类处理,但是,在需要转型的时候,编译器会根据T的类型自动为我们实行安全地强制转型。

限定类型

原始类型用第一个限定来替换类型变量,或者,如果没有给定限定,就替换为Object。

下面看一个使用了限定的泛型类

public static <T extends Comparable> T t (T ...args)
{
    T item = args[0];

    for (int i=1; i < args.length; i++)
        if (item.compareTo(args[i]) > 0)
            item = args[i];

    return item;
}

原始类型如下:

public static Comparable t (Comparable ...args)
{
    Comparable item = args[0];

    for (int i=1; i < args.length; i++)
        if (item.compareTo(args[i]) > 0)
            item = args[i];

    return item;
}