GetMethods() возвращает метод, который я не определял при реализации общего интерфейса

Простой интерфейс:

interface Foo {
    void myMethod(String arg);
}

class FooImpl implements Foo {
    void myMethod(String arg){}

    public static void main(String[] args) {
    Class cls = FooImpl.class;
    try {
        for (Method method : cls.getMethods()) {
        System.out.print(method.getName() + "\t");
        for(Class paramCls : method.getParameterTypes()){
            System.out.print(paramCls.getName() + ",");
        }
        System.out.println();
        }
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
    }
    }
}

Вывод будет:

myMethod java.lang.String,
...//Other Method

Распечатывается только один myMethod.

Но если я изменил интерфейс на общий:

interface Foo<T> {
    void myMethod(T arg);    
}   

class FooImpl implements Foo<String> {
    void myMethod(String arg){}
}

Тогда странно вывод будет:

myMethod java.lang.Object,
myMethod java.lang.String,
...//Other Method

Почему после изменения интерфейса на общий он приведет к еще одному методу с типом параметра Object?

Ответ 1

Первый метод - это метод моста, созданный компилятором. Если вы проверите свои методы для isBridge() ', вы можете отфильтровать "неправильные" методы (также отфильтровывает некоторые странные результаты, которые вы можете получить с возвратом ковариации).

Следующий код не распечатает myMethod java.lang.Object:

import java.lang.reflect.Method;


public class FooImpl implements Foo<String> {
    public void myMethod(String arg) {
    }

    public static void main(String[] args) throws Exception {
        Class cls = FooImpl.class;
        for (Method method : cls.getMethods()) {
            if (!method.isBridge()) {
                System.out.print(method.getName() + "\t");

                for (Class paramCls : method.getParameterTypes()) {

                    System.out.print(paramCls.getName() + ",");

                }
            }
            System.out.println();
        }
    }
}

interface Foo<T> {
    public void myMethod(T arg);
}

Ответ 2

try {
        for (Method method : cls.getMethods()) {
    //these methods are called bridge methods       
            if(!method.isBridge()){
                System.out.print(method.getName() + "\t");
                for(Class paramCls : method.getParameterTypes()){
                    System.out.print(paramCls.getName() + ",");
                }
                System.out.println();
            }
        }
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
    }

ОБНОВЛЕНИЕ: Модные методы

Цитирование блога:

Мост-методы в Java - это синтетические методы, которые необходимы для реализовать некоторые функции языка Java. Наиболее известные образцы ковариантный тип возврата и случай в дженериках при стирании базы аргументы метода отличаются от действительного вызываемого метода.

КОД ОБНОВЛЕНИЯ ОТ выше:

public class SampleTwo {
    public static class A<T> {
        public T getT(T args) {
            return args;
        }
    }

    public static class B extends A<String> {
        public String getT(String args) {
            return args;
        }
    }
}

При компиляции код будет выглядеть так:

public SampleThree$B();
...
public java.lang.String getT(java.lang.String);
Code:
0:   aload_1
1:   areturn

public java.lang.Object getT(java.lang.Object);
Code:
0:   aload_0
1:   aload_1
2:   checkcast       #2; //class java/lang/String
5:   invokevirtual   #3; //Method getT:(Ljava/lang/String;)Ljava/lang/String;
8:   areturn
}

метод bridge, который переопределяет метод из базового класса "A", а не просто вызывающий один со строковым аргументом (# 3), но также выполняющий тип добавлен в "java.lang.String" (# 2). Это означает, что если вы выполните следующий код, игнорируя предупреждение "unchecked" компилятора, результат будет исключение ClassCastException из метода моста:

A a = new B();
a.getT(new Object()));