Javagenerics – Bridge方法?

与Javagenerics相关的一个叫做“桥接方法”的概念让我停下来想一想。

顺便说一句,我只知道它发生在字节码级别,并不适合我们使用。

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

幕后究竟发生了什么以及为什么它被使用?

任何帮助示例将不胜感激。

这是一种允许扩展generics类或实现通用接口(具有具体types参数)的类继续用作原始types的方法。

想象一下:

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

这不能用于原始forms,传递两个Object来进行比较,因为types被编译到比较方法中(与将会发生的genericstypes参数T相反,types将被擦除)。 相反,在幕后,编译器添加了一个“桥接方法”,看起来像这样(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); } } 

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

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

为什么还需要?

除了增加支持显式使用原始types(主要是为了向后兼容)桥接方法也需要支持types擦除。 使用types擦除,像这样的方法:

 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 …只有一个这需要两个Integer

下面的FAQ是一个很好的阅读。

也可以看看:

  • generics常见问题解答 – 什么是桥接方法?
  • Java桥梁方法解释 (谢谢@Bozho )

注意到编译器推断MyComparator的方法是很MyComparator的:

 public int compare(Integer a, Integer b) {/* code */} 

正试图覆盖Comparator<T>

 public int compare(T a, T b); 

从声明的typesComparator<Integer> 。 否则, MyComparatorcompare将被编译器视为额外的(重载),而不是重写方法。 因此,将没有创build它的桥梁方法。