Проблема в GetDeclaredMethods (Java) - PullRequest
       13

Проблема в GetDeclaredMethods (Java)

8 голосов
/ 25 декабря 2009

У меня небольшая проблема в моем коде

У меня 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 находит также foo в классе A? как я могу это исправить?

спасибо

Ответы [ 6 ]

17 голосов
/ 25 декабря 2009

Причина, по которой у вас возникла проблема, заключается в ковариантных типах возврата двух ваших методов. Поскольку у вас есть ковариантный тип возвращаемого значения (тип возвращаемого значения 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());
   }   
}
2 голосов
/ 25 декабря 2009

По умолчанию 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());
  }
}

РЕДАКТИРОВАТЬ: Приведенный выше код не работает должным образом - он возвращает B в качестве декларирующего класса всех методов. Кажется, что метод isSynthetic() работает должным образом, возвращая true для переопределенного метода (тот, который пришел от A), но false для метода, который пришел от B. Поэтому следующий код может быть тем, что вы ищете.

Method[] m = b.getClass().getDeclaredMethods();
for (int i = 0; i < m.length; i++) {
  if (!m[i].isSynthetic()) {
    System.out.print(m[i]);
  }
}
1 голос
/ 25 декабря 2009

Потому что B.foo и A.foo это разные методы. Если вы хотите переопределить метод A.foo, то метод B.foo должен вернуть класс A.

0 голосов
/ 26 декабря 2009

Когда вы говорите, что (! AMethods.contains (m)) содержит сравнение по имени? Тип аргументов? тип возвращаемого значения? потому что единственное отличие от требуемого метода от not - это возвращаемый тип ковариации ...

0 голосов
/ 25 декабря 2009

Это может работать:

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
  }
}
0 голосов
/ 25 декабря 2009

Вы можете вызвать m.getDeclaringClass (), чтобы узнать, является ли это методом класса A или класса B.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...