Получение метода Java без использования getDeclaredMethod - PullRequest
2 голосов
/ 13 марта 2009

Я хочу инициализировать массив java-методов в дочернем классе, как поле класса , вот так

void callme() {System.out.println("hi!");}
Method[] actions = new Method[] {&callme,&callme};

и вызовите все методы в этом массиве в родительском классе следующим образом:

for (meth:actions) {meth.invoke();}

Однако в настоящее время я не могу найти способ неявной инициализации массива действий, а не через конструктор. Следующее дает мне ошибку из-за необработанного исключения:

Method[] actions = new Method[] {
    this.getClass().getDeclaredMethod("count")
};

Как уже говорилось, я не могу поймать исключение при явной инициализации этого массива в виде поля, а не в конструкторе.

Я новичок в Java-рефлексии, так что это, вероятно, очевидный вопрос, но я не нашел ответа на этот вопрос в Google, любая помощь будет принята.

Спасибо

приписка

Как Скотт ниже догадался, я "хочу, чтобы суперкласс вызывал определенный набор методов, определенных в подклассе".

Ответы [ 6 ]

3 голосов
/ 13 марта 2009

[Примечание: приведенный ниже код не был скомпилирован, но должен разобраться в этом]

Я должен повторить - чего вы пытаетесь достичь?

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

С отражением , я бы рекомендовал использовать аннотации:

1) определить аннотацию HeySuperclassCallMe (убедитесь, что срок хранения равен RUNTIME)

2) комментируйте методы для вызова с HeySuperclassCallMe

@HeySuperclassCallMe public void foo...

3) в вашем суперклассе сделайте что-то вроде

for (Method m : getClass().getMethods())
  if (m.getAnnotation(HeySuperclassCallMe.class) != null)
     m.invoke(...)

Это хороший рефлексивный способ сделать это.

Для без отражения (что должно быть немного быстрее, но больше кода):

1) определить интерфейс, который представляет вызовы

 public interface Call {
     void go();
 }

2) в вашем суперклассе определите

 private List<Call> calls
 protected void addCall(Call call)

3) в подклассе используйте addCall:

 addCall(new Call() {public void go() {foo();}} );

4) в суперклассе

 for (Call call : calls)
    call.go();
3 голосов
/ 13 марта 2009

Вы уверены, что рефлексия - это то, что нужно делать? Обычно интерфейс с несколькими анонимными классами, реализующими его, был бы лучшим стилем.

Вы можете написать блок инициализатора, чтобы иметь возможность перехватывать исключение во время инициализации.

Почему бы вам не использовать getMethod ()?

2 голосов
/ 13 марта 2009

Проверьте Apache Commons - Beanutils ! Это как обертка вокруг всего отражения, которая очень проста в использовании. Оборачивает вызов метода, изменяет атрибуты, ищет ...

Если вы хотите внедрить динамические в Java, вы должны взглянуть на динамические языки JVM, которые могут быть использованы простым включением библиотеки .jar! Один из них - Groovy , который содержит синтаксис java и обладает множеством динамических функций (создание сценариев, быстрое создание прототипов, мета-объектный протокол, перераспределение методов выполнения, динамические прокси ...).

0 голосов
/ 13 марта 2009

Я могу сказать по вашим амперсандам, что вы думаете на C. Мы на самом деле не используем указатели на функции в java.

Как правило, вы бы не использовали для этого отражения java. Как сказал один из других авторов, вы должны создать интерфейс и иметь объекты, которые реализуют этот интерфейс - либо непосредственно его реализуя, либо с помощью адаптера или анонимного класса:

interface Callable { void callme(); }

Callable[] foo = new Callable[] {
  new Callable() { public void callme() {System.out.println("foo!");}},
  new Callable() { public void callme() {System.out.println("bar!");}}
};

for(Callable c: foo) {
  c.callme();
}
0 голосов
/ 13 марта 2009

Это должно работать до тех пор, пока ваш метод действительно объявлен в this.getClass (). Если он унаследован, вам следует использовать Class.getMethod ().

Однако вместо использования указателей на функции в Java можно было бы определить интерфейс с методом, который нужно вызвать, и позволить этому интерфейсу быть реализованным целевым объектом.

Также рассмотрите возможность использования ArrayList или других классов коллекции вместо массивов.

0 голосов
/ 13 марта 2009

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

private static Method[] declaredMethods(Class<T> clazz, String methodName) {
  Method[] result = new Method[1];
  try{
    result[0] = clazz.getDeclaredMethod(methodName);
  } catch (NoSuchMethodException nsme) {
    // respond to the error
  } catch (SecurityException se)  {
    // Respond to the error
  }

  return result;
}

Method[] actions = declaredMethods("count");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...