Java编译器对多个泛型边界做了什么?

时间:2010-11-23 16:39:42

标签: java generics type-erasure

看看这个(可以说是愚蠢的)代码:

public <T extends Appendable & Closeable> void doStuff(T object)
throws IOException{

    object.append("hey there");
    object.close();

}

我知道编译器删除了一般信息,所以我对编译器所做的Java 1.4代码感兴趣(我很确定编译器没有重新安排源代码,所以我要求一个等价的像我这样天真的人可以理解的Java源代码版本)

是这样的:

public void doStuff(Object object)
throws IOException{

    ((Appendable)object).append("hey there");
    ((Closeable)object).close();

}

或者更喜欢这样:

public void doStuff(Object object)
throws IOException{
    Appendable appendable = (Appendable) object;
    Closeable closeable = (Closeable) object;

    appendable.append("hey there");
    closeable.close();

}

或者甚至喜欢这样:

public void doStuff(Appendable appendable)
throws IOException{
    Closeable closeable = (Closeable) appendable;

    appendable.append("hey there");
    closeable.close();

}

还是另一个版本?

2 个答案:

答案 0 :(得分:14)

方法的签名看起来像public void doStuff(Appendable appendable),因为

  

绑定中类型的顺序是   唯一重要的是,类型变量的擦除由第一种类型决定   在它的绑定中,类类型或类型变量可能只出现在第一个中   位置。

JLS §4.4 Type Variables

如果使用反射来访问此方法,则此行为可能很重要。

此行为的另一个用途是保留与预通用接口的二进制兼容性,如 Generics Tutorial ,第10节中所述(感谢Mark Peters指出它)。也就是说,

public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll)

与返回Object的预通用版本二进制兼容。


方法体等同于以下内容,但我认为它是实现细节:

appendable.append("hey there"); 
((Closeable) appendable).close(); 

答案 1 :(得分:4)

我等不及了,我不得不回答我自己的问题。答案是我的第一个和第三个版本的组合:第一个绑定用作变量类型,并且对象在需要时被转换为第二个绑定。这是生成的字节代码(为了便于阅读,我添加了一个换行符):

  // Method descriptor #20 (Ljava/lang/Appendable;)V
  // Signature: <T::Ljava/lang/Appendable;:Ljava/io/Closeable;>(TT;)V
  // Stack: 2, Locals: 2
  public void doStuff(java.lang.Appendable object) throws java.io.IOException;
     0  aload_1 [object]
     1  ldc <String "hey there"> [26]
     3  invokeinterface java.lang.Appendable.append(java.lang.CharSequence) :
        java.lang.Appendable [28] [nargs: 2]
     8  pop
     9  aload_1 [object]
    10  checkcast java.io.Closeable [34]
    13  invokeinterface java.io.Closeable.close() : void [36] [nargs: 1]
    18  return
      Line numbers:
        [pc: 0, line: 14]
        [pc: 9, line: 15]
        [pc: 18, line: 17]
      Local variable table:
        [pc: 0, pc: 19] local: this index: 0 type: rumba.dumba.Bumba
        [pc: 0, pc: 19] local: object index: 1 type: java.lang.Appendable
      Local variable type table:
        [pc: 0, pc: 19] local: object index: 1 type: T