简体   繁体   English

BeanInfo:methodDescriptors和类之间的差异:declaredMethods:具有相同名称和方法屏蔽的多个方法

[英]Differences between BeanInfo:methodDescriptors and class:declaredMethods : multiple methods with same name and method masking

When trying to get JPA annotations at runtime for some properties, I encountered this problem. 当试图在运行时为某些属性获取JPA注释时,我遇到了这个问题。 I can't explain why. 我无法解释原因。

PS: after a debugging session with Spring, I found the explanation of this problem: bridged methods that are introduced at compile time by the compiler. PS:在与Spring的调试会话之后,我找到了这个问题的解释:编译器在编译时引入的桥接方法。 Please see my own answer to this question.. 请看我自己对这个问题的回答..

Here is a sample source code replicating the issue (simplified version of real code). 以下是复制问题的示例源代码(实际代码的简化版本)。

import java.beans.BeanInfo; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.Introspector; import java.beans.MethodDescriptor; import java.beans.MethodDescriptor; import java.io.Serializable; import java.io.Serializable; import java.lang.reflect.Method; import java.lang.reflect.Method;

public class MethodMasking { 公共类MethodMasking {

public interface HasId<ID extends Serializable>  {
    void setId(ID id);
    ID getId();
}

public interface Storeable extends HasId<Long> {}

class Item implements Storeable {Long id; String code;
    Item(Long id, String code) { this.id = id; this.code = code; }
    public Long getId() { return id; }
    public void setId(Long id) {this.id = id;}
}

public static void main(String[] args) throws IntrospectionException {
    final BeanInfo beanInfo = Introspector.getBeanInfo(Item.class);

    java.lang.System.out.println("BeanInfo:methodDescriptors:");
    final MethodDescriptor[] methodDescriptors = beanInfo.getMethodDescriptors();
    for (MethodDescriptor methodDescriptor : methodDescriptors) {
        java.lang.System.out.println("\t"+methodDescriptor.getMethod().getName());
    }

    java.lang.System.out.println("class:declaredMethods:");
    final Method[] declaredMethods = Item.class.getDeclaredMethods();
    for (Method declaredMethod : declaredMethods) {
        java.lang.System.out.println("\t"+declaredMethod.getName());
    }
}

} Output of the program: 输出程序:

BeanInfo:methodDescriptors:
    hashCode
    wait
    getId
    notifyAll
    equals
    wait
    wait
    toString
    setId
    notify
    setId
    getClass
class:declaredMethods:
    getId
    getId
    setId
    setId

Now I'm confused: 现在我很困惑:
why in beanInfo there are 2 methods descriptors for setId but only one for getId ? 为什么在beanInfo中有4个方法描述符用于setId但只有一个用于getId?
why in declared method there are 2 methods for getId and 2 methods for setId ? 为什么在声明的方法中有4个getId方法和2个setId方法?

While debugging I have these methods signatures when using the getDeclaredMethods : 在调试时,我使用getDeclaredMethods时有这些方法签名:

[0] = {java.lang.reflect.Method@139}"public java.lang.Long MethodMasking$Item.getId()"
[1] = {java.lang.reflect.Method@446}"public java.io.Serializable MethodMasking$Item.getId()"
[2] = {java.lang.reflect.Method@447}"public void MethodMasking$Item.setId(java.lang.Long)"
[3] = {java.lang.reflect.Method@448}"public void MethodMasking$Item.setId(java.io.Serializable)"

Edit: After some tests I have found that the cause of the problem is the usage of generics in the HasId interface... 编辑:经过一些测试后我发现问题的原因是HasId接口中泛型的使用...

Declared this way, the problem disapear: no more duplicate methods. 用这种方式声明,问题消失了:没有更多重复的方法。

public interface HasId  {
        void setId(Long id);
        Long getId();
    }

    public interface Storeable extends HasId {} 

It is because the compiler is introducing bridge methods when Generics are used: 这是因为编译器在使用泛型时引入了桥接方法
some explanation here 这里有一些解释

Print out more information about the methods your receive : not only their names but param lists. 打印出有关您收到的方法的更多信息:不仅是他们的名字,还包括参数列表。 Try to have enough information to distinguish overrides and averloads. 尝试获取足够的信息来区分覆盖和averloads。 The difference can come from this but it's still not clear for me. 差异可能来自于此,但对我来说仍然不明确。

Regards, Stéphane 此致,Stéphane

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM