2009-03-13 4 views
2

Я хочу, чтобы инициализировать массив методов ява в дочернем классе, как поле класса как такПолучение метода Java без использования getDeclaredMethod

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, любая помощь будет оценена.

P.S.

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

+0

Что на Земле вы пытаетесь сделать ? –

+0

Как полагает Скотт ниже, я пытаюсь «Если вы хотите, чтобы суперкласс вызывал определенный набор методов, определенных в подклассе» –

ответ

-2

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

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"); 
+0

Это сработало бы, но это так же уродливо, как ... ну, как уродливо, как Java иногда is ;-) –

+0

Никто не может остановить вас, объявив статический метод declareMethods (класс clazz, String) в отдельном классе с помощью частного конструктора и скрыть все уродливые детали. Еще лучше вы можете использовать некоторую библиотеку Apache Commons. –

+0

«Ответьте на ошибку» ??? –

2

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

Если вы хотите включить динамическое на Java, вы должны посмотреть динамические языки JVM, которые могут быть использованы простым, включая библиотеку .jar! Из них Groovy, который содержит синтаксис java и обеспечивает множество динамических функций (сценариев, быстрого прототипирования, Meta-Object-Protocol, runtime-method reacement, dynamic proxies ...).

3

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

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

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

0

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

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

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

3

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

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

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

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

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

Я думал о технике аннотации, но мне не нравится, что вы не можете указать заказ. На самом деле я в конце концов сделал @UseMessage (order = 0). Которая работала нормально, но УГЛИ УГЛИ УГЛИ. (и сложнее поддерживать, так как нельзя легко вставить метод между ними). –

+0

BTW: Если вы называете атрибут «значение», вы можете использовать его без имени атрибута: @UseMessage (0). Впрочем, это не помогает упорядочению. –

0

Я могу сказать вашим амперсандами, что вы думаете в 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(); 
} 
Смежные вопросы