Java - 通用类型 - 类型擦除

时间:2012-12-29 00:45:55

标签: java generics

我在oracle网站上找到了以下问题和答案

以下类在类型擦除后转换为什么?

public class Pair<K, V> {

    public Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey(); { return key; }
    public V getValue(); { return value; }

    public void setKey(K key)     { this.key = key; }
    public void setValue(V value) { this.value = value; }

    private K key;
    private V value;
}

答案:

public class Pair {

    public Pair(Object key, Object value) {
        this.key = key;
        this.value = value;
    }

    public Object getKey()   { return key; }
    public Object getValue() { return value; }

    public void setKey(Object key)     { this.key = key; }
    public void setValue(Object value) { this.value = value; }

    private Object key;
    private Object value;
}

但是当我使用JD-GUI反编译类文件时,我仍然看到所有通用类型与实际源代码中的类似。

这是否意味着泛型类型保留在类文件中?我正在使用Java 6.

使用JD-GUI的类的反编译器版本如下。我正在使用Eclipse Helios编译该类。

public class Pair<K, V>
{
  private K key;
  private V value;

  public Pair(K key, V value)
  {
    this.key = key;
    this.value = value;
  }
  public K getKey() {
    return this.key; } 
  public V getValue() { return this.value; } 
  public void setKey(K key) {
    this.key = key; } 
  public void setValue(V value) { this.value = value;
  }
}

1 个答案:

答案 0 :(得分:6)

.class文件中保留了一些泛型类型信息 - 足以允许您通过反射确定类型Pair是通用的,对于具有Pair成员的类,通用参数的类型是什么等等上。保留此信息的事实构成了super type tokens等技术的基础,允许您传递保留有关其通用参数的信息的类型令牌。

然而,在反射之外,类型擦除意味着Pair类的行为与Oracle网站的“答案”中的剥离版本大致相同。特别是,方法的实际字节码不会引用泛型类型KV - 仅对象,方法签名将接受并返回Object

在这种情况下,JD-GUI只是很聪明,并使用存储在.class文件中的信息来恢复反编译输出中的通用信息,但请确保在字节码中删除类型。