Различия между BeanInfo: methodDescriptors и class: declaredMethods: несколько методов с одинаковыми именами и маскировкой методов


При попытке получить аннотации JPA во время выполнения для некоторых свойств, я столкнулся с этой проблемой. Я не могу объяснить почему.

PS: после сеанса отладки с Spring я нашел объяснение этой проблемы: мостовые методы, которые вводятся компилятором во время компиляции. Пожалуйста, посмотрите мой собственный ответ на этот вопрос..

Вот пример исходного кода, воспроизводящего проблему (упрощенная версия реального кода).

Импорт java.зернышки.Beaninfo, которые; импортировать Ява.зернышки.IntrospectionException; импорт java.зернышки.Самоанализа; импорт java.зернышки.MethodDescriptor; импорт Java.Ио.Сериализуемый; импорт java.яз..отражать.Метод;

Маска метода открытого класса {

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

} Выходные данные программы:

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

Теперь я в замешательстве:
почему в информации о компоненте существует 2 метода дескрипторов для setId, но только для getId ?
почему в объявленном методе есть 2 метода для getId и 2 метода для setId ?

Во время отладки у меня есть эти методы сигнатуры при использовании 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)"

Править: После некоторых тестов я обнаружил, что причиной проблемы является использование дженериков в интерфейсе HasId...

Объявленная таким образом, проблема исчезает: больше нет дублирующих методов.

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

    public interface Storeable extends HasId {} 
2 3

2 ответа:

Это происходит потому, что компилятор вводит мостовые методы , когда используются универсальные методы:
некоторое объяснение здесь

Распечатайте дополнительную информацию о методах, которые вы получаете : не только их имена,но и списки параметров. Постарайтесь иметь достаточно информации, чтобы различать переопределения и усреднения. Разница может исходить из этого, но это все еще не ясно для меня.

С уважением, Стефан