Java 比较器两种反射比较方法

Java 比较器两种反射比较方法,java,generics,reflection,Java,Generics,Reflection,我试图解决一个未知比较器的问题(无源访问)。 所以我写了一些反射代码来看看比较器接受什么类型 令人惊讶的是,反射告诉我,有两种比较方法,一种是实数类型,另一种是Object: Comparator<Integer> comp = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return 0; } };

我试图解决一个未知比较器的问题(无源访问)。 所以我写了一些反射代码来看看比较器接受什么类型

令人惊讶的是,反射告诉我,有两种比较方法,一种是实数类型,另一种是Object:

Comparator<Integer> comp = new Comparator<Integer>()
{

    @Override
    public int compare(Integer o1, Integer o2)
    {
        return 0;
    }
};

Method[] methods = comp.getClass().getMethods();
for (Method method : methods)
{
    if(method.getName().equals("compare")){
        System.out.println(method);
    }
}
第二个
比较
方法来自哪里?

但它不可用,为什么

comp.compare(1, 2); //Compiles
comp.compare((Object)1,(Object)2); //Does not Compile
但是,我可以使用反射调用这些方法,如果我使用
new Object()
调用这两个方法,我将得到两个不同的异常:

compare(java.lang.Object,java.lang.Object)
java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.Integer

compare(java.lang.Integer,java.lang.Integer)
java.lang.IllegalArgumentException: argument type mismatch
如果用Object定义我的比较器,那么只有一种方法。

这是因为,这是Java中泛型实现中的设计决策(保留向后兼容性)

在类型擦除过程中,如果类型参数有界,Java编译器将擦除所有类型参数,并用其第一个界替换每个类型参数;如果类型参数无界,则用对象替换每个类型参数

这允许从Java-5之前的JVM访问您的类,其中
Comparator
不可见,但
Comparator
可见(它提供
compare(Object,Object)
)。
compare(Object,Object)
的实现只是将每个参数强制转换为一个整数,并调用
compare(Integer,Integer)
,这就是为什么会出现异常。

另一种方法(
compare(Object obj1,Object2
)是由编译器生成的,用于在类型擦除后保持二进制兼容性:

编译扩展参数化类或实现参数化接口的类或接口时,编译器可能需要创建称为桥接方法的合成方法,作为类型擦除过程的一部分。通常不需要担心桥接方法,但如果堆栈跟踪中出现桥接方法,则可能会感到困惑

您可以在方法上添加检查,以查看它是否为桥接方法:

for (Method method : methods) {
    if (method.getName().equals("compare") && !method.isBridge()) {
        System.out.println(method);
    }
}
for (Method method : methods) {
    if (method.getName().equals("compare") && !method.isBridge()) {
        System.out.println(method);
    }
}