Java 泛型 - 桥接方法?

标签 java generics

与 Java Generics 相关的称为“桥接方法”的概念让我停下来思考一下。

Btw, I only know that it occurs at the bytecode level and is not available for us to use.

但我很想知道 Java 编译器使用的“桥接方法”背后的概念。

幕后到底发生了什么,为什么要使用它?

如能提供示例帮助,我们将不胜感激。

最佳答案

它是一种允许扩展泛型类或实现泛型接口(interface)(带有具体类型参数)的类仍然用作原始类型的方法。

想象一下:

public class MyComparator implements Comparator<Integer> {
   public int compare(Integer a, Integer b) {
      //
   }
}

这不能以其原始形式使用,传递两个 Object s 进行比较,因为类型被编译到比较方法中(与泛型类型参数 T 会发生的情况相反,其中类型将被删除)。因此,在幕后,编译器添加了一个“桥接方法”,它看起来像这样(如果是 Java 源代码):

public class MyComparator implements Comparator<Integer> {
   public int compare(Integer a, Integer b) {
      //
   }

   //THIS is a "bridge method"
   public int compare(Object a, Object b) {
      return compare((Integer)a, (Integer)b);
   }
}

编译器保护对桥方法的访问,强制直接显式调用它会导致编译时错误。现在该类也可以以其原始形式使用:

Object a = 5;
Object b = 6;

Comparator rawComp = new MyComparator();
int comp = rawComp.compare(a, b);

为什么还需要它?

除了添加对显式使用原始类型的支持(主要是为了向后兼容)之外,还需要桥接方法来支持类型删除。使用类型删除,这样的方法:

public <T> T max(List<T> list, Comparator<T> comp) {
   T biggestSoFar = list.get(0);
   for ( T t : list ) {
       if (comp.compare(t, biggestSoFar) > 0) {
          biggestSoFar = t;
       }
   }
   return biggestSoFar;
}

实际上被编译成与此兼容的字节码:

public Object max(List list, Comparator comp) {
   Object biggestSoFar = list.get(0);
   for ( Object  t : list ) {
       if (comp.compare(t, biggestSoFar) > 0) {  //IMPORTANT
          biggestSoFar = t;
       }
   }
   return biggestSoFar;
}

如果桥接方法不存在并且您传递了一个 List<Integer>和一个 MyComparator对于此函数,调用标记为 IMPORTANT 的行自 MyComparator 后会失败将没有名为 compare 的方法这需要两个 Object s...只有一个需要两个Integer

下面的常见问题是一个很好的阅读。

另请参阅:

关于Java 泛型 - 桥接方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48856567/

相关文章:

c# - 有没有一种方法可以在不显式传递通用类型的情况下对结果集合调用 DbContext.Translate?

java - 使用 Java 泛型可能会挂起编译器

c# - 具有通用参数的类的名称?

java - 属性文件的无序输出

java - 如何安装JDBC以及如何使用它来连接mysql?

generics - Haxe 泛型 - 花括号作为约束

c# - 是否可以在 ServiceStack.Text 中为开放泛型类型设置自定义(反)序列化器?

JavaFX HMTLEditor 对 'return' 键没有反应

java - 如何确保始终调用 finalize()(Thinking in Java 练习)

java - OnCompleteListener 和 CompletionListener 之间有什么区别?