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