Динамические переменные с заданным типом - PullRequest
1 голос
/ 09 августа 2010

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

Мой класс использует на данный момент следующий код для считывания аннотации:

ExtendedCommandAnnotation e = foo.getClass()
                                 .getAnnotation(ExtendedCommandAnnotation.class);
String startTag = e.annoPropStartTag();

Это простой случай с фиксированной аннотацией.
В новой версии у меня нет фиксированной аннотации. Я получу аннотацию ExtendedCommandAnnotation в переменной.
Поэтому приведенный выше код будет отредактирован по адресу:

String className= "ExtendedCommandAnnotation";
??? e = foo.getClass().getAnnotation(Class.forName(className));
String startTag = e.annoPropStartTag();

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

Моя аннотация "класс":

@Retention( RetentionPolicy.RUNTIME )
public @interface ExtendedCommandAnnotation
{
    String   annoPropUseTab() default "0";
    String   annoPropStartTag() default "";
    String   annoPropEndTag() default "";
}

EDIT:

Наконец-то я получаю нечто подобное: String [] cmdMethNames = this.getAvailableCommandNames ();

    Class<?> annotationClass = Class.forName(this.annotationClassName); 

    for( Method meth : cmdMeth )
    {
        HashMap<String, String> tempAnno = new HashMap<String, String>();
        if (meth.isAnnotationPresent((Class<? extends Annotation>) annotationClass))
        {
            Annotation anno = meth.getAnnotation((Class<? extends Annotation>) annotationClass);
            [...]
        }
        [...]
    }

Но приведение к (Class<? extends Annotation>) делает следующее предупреждение: " Безопасность типов: непроверенное приведение из класса В Class <? Extends Аннотация> "

Ответы [ 2 ]

2 голосов
/ 09 августа 2010

Если вы не знаете аннотацию заранее, вы не можете знать, что у нее есть метод annoPropStartTag(), не так ли? Таким образом, вы не можете указать компилятору, как связываться с этим методом ...

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

Возможно, вы захотите рассмотреть какой-нибудь «базовый» тип аннотации, который содержит все методы, которые вам нужны в общем случае, а затем вывести все остальные типы аннотаций из этого.

1 голос
/ 12 августа 2010
/* Foo.java */

@ExtendedCommandAnnotation(annoPropStartTag = "hello")
public class Foo {
}

/* ExtendedCommandAnnotation.java */

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention( RetentionPolicy.RUNTIME )
public @interface ExtendedCommandAnnotation {
    String annoPropUseTab() default "0";
    String annoPropStartTag() default "";
    String annoPropEndTag() default "";
}

/* Main.java */

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class Main {
    public static void main(String[] args) {
        doOriginalImplementation();     // Prints "hello"
        doReflectionImplementation();   // Prints "hello"
    }

    public static void doOriginalImplementation() {
        Foo foo = new Foo();
        ExtendedCommandAnnotation e = foo.getClass().getAnnotation(ExtendedCommandAnnotation.class);
        String startTag = e.annoPropStartTag();
        System.out.println(startTag);
    }

    public static void doReflectionImplementation() {
        Foo foo = new Foo();

        Annotation[] annotations = foo.getClass().getAnnotations();
        // or the statement below, depends on what you intent to do:
        // Annotation[] annotations = foo.getClass().getDeclaredAnnotations();

        Class classOfExtendedCommandAnnotation = null;
        Annotation annotationOnClassFoo = null;
        for (Annotation a : annotations) {
            Class classA = a.annotationType();
            if ("ExtendedCommandAnnotation".equals(classA.getName())) {
                classOfExtendedCommandAnnotation = classA;
                annotationOnClassFoo = a;
                break;
            }
        }

        Method methodAnnoPropStartTag = null;
        if (classOfExtendedCommandAnnotation != null) {
            try {
                methodAnnoPropStartTag = classOfExtendedCommandAnnotation.getMethod("annoPropStartTag");
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }

        if (methodAnnoPropStartTag != null) {
            try {
                String startTag = (String) methodAnnoPropStartTag.invoke(annotationOnClassFoo);
                System.out.println(startTag);
            } catch (ClassCastException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

В моем решении класс ExtendedCommandAnnotation не обязательно должен присутствовать во время компиляции.Тем не менее, класс Foo должен присутствовать.Решение может быть немного изменено, так что класс Foo также не обязательно должен присутствовать.

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