Как игнорировать модификаторы при вызове методов во время выполнения - JAVA

1

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

Моя проблема в том, что могут быть некоторые защищенные методы, частные и т.д., И я хотел бы игнорировать эти модификаторы и получить доступ ко всем методам (т.е. Даже если это частный и т.д.),

Так вот как я вызываю (дано имя аннотации, которую я ищу:

if (m.isAnnotationPresent(Given.class)) {
        m.invoke(instObj, intArgument);
 }

(И вот как я проверяю остальную иерархию классов - если я где-то ошибся, просветите меня, пожалуйста:

Class<?> superC = c.getSuperclass();
while (!(superC.equals(Object.class))) {
                handleGiven(instObj, superC, methods, currentSentence,
                        methodArgument);

когда handleGiven является рекурсивным вызовом.

  • 0
    Вы ищете getDeclaredMethods ?
  • 0
    Я использовал getMethods, на самом деле.
Показать ещё 5 комментариев
Теги:
reflection
oop

2 ответа

2
Лучший ответ

Вам нужно использовать getDeclaredMethods для получения всех методов (общедоступных, защищенных и т.д.), Например:

public Method findMethodWithAnnotation(Class<?> clazz,
        Class<? extends Annotation> annotation) {
    for (Method m : clazz.getDeclaredMethods()) {
        if (m.isAnnotationPresent(annotation)) {
            return m;
        }
    }
    return null;
}

И проверьте следующее:

    Class<?> clazz = ..; //get the class
    Method m = null;
    do {
        m = findMethodWithAnnotation(clazz, DesiredAnnotation.class);
        clazz = clazz.getSuperclass();
    } while (m == null && clazz != null);
    System.out.println(m);

Также убедитесь, что ваша аннотация имеет следующую аннотацию:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)

Если вам нужна аннотация для полей, проверьте методы getDeclaredFields и similars.

Вы должны сделать доступный метод до вызова

m.setAccessible(true);

Если вы хотите более компактную и рекурсивную реализацию, вы можете изменить на:

public Method findMethodWithAnnotation(Class<?> clazz,
        Class<? extends Annotation> annotation) {

    if (clazz == Object.class || clazz == null) return null;
    for (Method m : clazz.getDeclaredMethods()) {
        if (m.isAnnotationPresent(annotation)) {
            return m;
        }
    }
    return findMethodWithAnnotation(clazz.getSuperClass(), annotation);
}

И использование:

Method m = findMethodWithAnnotation(clazz, DesiredAnnotation.class)
if (m == null) log("Nor the class, or any superclass have the desired annotation")
else {
    m.setAccessitble(true);
    m.invoke(obj, arguments);
}

Соображения:

  • это не покрывает интерфейсы, если вам нужно покрыть интерфейсы, проверьте getInterfaces() (этот метод возвращает интерфейсы в порядке объявления).
  • Если aa класс A имеет метод переопределения, desiredMethod метод, без аннотации, и расширяет класс SuperA, у него есть метод desiredMethod метод, с требуемой аннотацией, это возвращает SuperA#desiredMethod, но когда вы его вызываете, он будет вызываться в классе A (как обычный вызов)
  • 0
    Означает ли это, что мой импл. неправильно или это просто другое решение (для рекурсивной части)
  • 0
    Нет, ваше решение не является неправильным, это только полная реализация.
0

Моя проблема в том, что могут быть некоторые защищенные методы, частные и т.д., И я хотел бы игнорировать эти модификаторы и получить доступ ко всем методам (т.е. Даже если это частный и т.д.),

Вам необходимо вызвать Method.setAccessible(true) прежде чем вызывать его, не забывая впоследствии восстановить его исходное значение, в блоке finally.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню