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>
。 否则, MyComparator
的compare
将被编译器视为额外的(重载),而不是重写方法。 因此,将没有创build它的桥梁方法。