比较器二 compare Methods with Reflection

Comparator two compare Methods with Reflection

我正在尝试解决未知比较器的问题(无源访问权限)。 所以我写了一些反射代码来查看 Comparator 接受的类型。

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

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);
    }
}

输出:

public int de.hinneLinks.Whosebug.MyClass.compare(java.lang.Integer,java.lang.Integer)
public int de.hinneLinks.Whosebug.MyClass.compare(java.lang.Object,java.lang.Object)

第二个compare方法来自哪里?

但是不能用,为什么?:

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

如果用对象定义我的比较器,那么只有一个方法。

这是由于 Type Erasure,这是 Java.

泛型实现中的一个设计决定(保持向后兼容性)

During the type erasure process, the Java compiler erases all type parameters and replaces each with its first bound if the type parameter is bounded, or Object if the type parameter is unbounded.

这允许从 Java-5 之前的 JVM 访问您的 class,其中 Comparator<Integer> 不可见,但 Comparator 是(它提供 compare(Object, Object)). compare(Object, Object) 的实现只是将每个参数转换为一个整数并调用 compare(Integer, Integer),这就是你得到异常的原因。

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

When compiling a class or interface that extends a parameterized class or implements a parameterized interface, the compiler may need to create a synthetic method, called a bridge method, as part of the type erasure process. You normally don't need to worry about bridge methods, but you might be puzzled if one appears in a stack trace.

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

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