代码之家  ›  专栏  ›  技术社区  ›  Sean Patrick Floyd

Java编译器在多个通用边界上做什么?

  •  13
  • Sean Patrick Floyd  · 技术社区  · 14 年前

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

    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 回复  |  直到 10 年前
        1
  •  14
  •   Kevin K    10 年前

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

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

    ( JLS §4.4 Type Variables )

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

    这种行为的另一个用途是保持与前通用接口的二进制兼容性,如中所述。 Generics Tutorial ,第10节(感谢马克·彼得斯指出)。也就是说,

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

    二进制文件与其返回的前通用版本兼容吗? Object .


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

    appendable.append("hey there"); 
    ((Closeable) appendable).close(); 
    
        2
  •  4
  •   Sean Patrick Floyd    14 年前

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

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