Java 编译器如何处理多个泛型边界?

2022-09-04 02:29:44

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

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

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

}

我知道编译器会删除通用信息,所以我对Java 1.4代码感兴趣,这些代码等同于编译器所做的(我很确定编译器不会重新排列源代码,所以我要求一个等效的Java源代码版本,像我这样天真的人可以理解)

Is 是这样的:

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();

}

还是另一个版本?


答案 1

该方法的签名类似于 ,因为public void doStuff(Appendable appendable)

绑定中类型的顺序之所以重要,是因为类型变量的擦除由其绑定中的第一个类型确定,并且类类型或类型变量可能仅出现在第一个位置。

(JLS §4.4 类型变量)

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

此行为的另一个用途是保持与预通用接口的二进制兼容性,如泛型教程第 10 节所述(感谢 Mark Peters 指出这一点)。那是

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

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


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

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

答案 2

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

  // 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

推荐