开发者

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

开发者 https://www.devze.com 2023-03-26 07:04 出处:网络
When trying to get JPA annotations at runtime for some properties, I encountered this problem. I can\'t explain why.

When trying to get JPA annotations at runtime for some properties, I encountered this problem. 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. 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.Introsp开发者_开发技巧ectionException; import java.beans.Introspector; import java.beans.MethodDescriptor; import java.io.Serializable; import java.lang.reflect.Method;

public class 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 ?

why in declared method there are 2 methods for getId and 2 methods for setId ?

While debugging I have these methods signatures when using the 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...

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. The difference can come from this but it's still not clear for me.

Regards, Stéphane

0

精彩评论

暂无评论...
验证码 换一张
取 消