У меня есть небольшая проблема в моем коде
У меня есть 2 класса
public class A {
public A foo(int a) {return new A();}
}
public class B extends A{
public B foo(int x){ return new B();}
}
теперь в моем коде я хочу распечатать только метод, который был объявлен в классе B
таким образом
B b = new B();
Method[] m = b.getClass().getDeclaredMethods();
for (int i = 0; i < m.length; i++) {
System.out.print(m[i].getName());
}
почему вывод
foo
foo
почему GetDeclaredMethods находит также нечто в класс? как я могу зафиксировать его?
спасибо
Проблема возникает из-за ковариантных типов возвращаемых данных двух ваших методов. Поскольку у вас есть ковариантный тип возвращаемого значения (тип возвращаемого значения B - это B, а не A, в отличие от суперкласса), Java под капотом генерирует отдельный метод с исходным типом возврата, чтобы действовать как мост между спецификацией байт-кода до 1.5 и новое поведение языка Java 1.5.
Для проверки следует использовать метод isBridge ()
, поскольку он точно выражает то, что вы собираетесь исключить. Таким образом, окончательный код будет выглядеть примерно так:
Method[] methods = B.class.getDeclaredMethods();
for (Method method : methods) {
if (!method.isBridge()) {
System.out.println(method.getName());
}
}
По умолчанию getDeclaredMethods ()
возвращает все методы для данного класса, а также его родительские классы и интерфейсы. Однако объект Method
позволяет вам проверить, к какому классу принадлежит Method
, вызвав getDeclaringClass ()
для этого Method
. Поэтому, когда вы циклически перебираете все объекты Method
, вы можете добавить логику для печати метода, только если он принадлежит классу B
.
Method[] m = b.getClass().getDeclaredMethods();
for (int i = 0; i < m.length; i++) {
if (m[i].getDeclaringClass().equals(B.class)) {
System.out.print(m[i].getName());
}
}
EDIT: Приведенный выше код не работает должным образом - он возвращает B
как класс объявления всех методов. Метод isSynthetic ()
, похоже, работает должным образом, возвращая истину для замещенного метода (который пришел из A
), но ложь для той, что пришла из B
. Так что следующий код может быть тем, что вы ищете:
Method[] m = b.getClass().getDeclaredMethods();
for (int i = 0; i < m.length; i++) {
if (!m[i].isSynthetic()) {
System.out.print(m[i]);
}
}
Потому что B.foo и A.foo - это разные методы. Если вы хотите переопределить метод A.foo, тогда метод B.foo должен возвращать класс A.
Вы можете вызвать m.getDeclaringClass (), чтобы узнать, является ли это метод из класса A или класс B.
Это может сработать:
A a = new A();
B b = new B();
List<Method> aMethods = Arrays.asList(a.getClass().getMethods());
List<Method> bMethods = Arrays.asList(b.getClass().getMethods());
for ( Method m : bMethods )
{
if( ! aMethods.contains(m) )
{
//Your action code here
}
}
Когда вы говорите if( ! aMethods.contains(m) ) содержит сравнение по name? arguments type? return value type? потому что единственное отличие от метода-розыскивателя - тип возвращаемого ковариационного типа...