2010-08-09 2 views
1

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

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

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>) маркам следующее предупреждение: "Безопасность Тип:? Неконтролируемый отлиты из класса < захвата # 4-в> к классу < расширяет Annotation>"

ответ

1
/* 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 также не должен присутствовать.

2

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

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

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

+0

Спасибо за редактирование моего вопроса. Но когда я использую метод getMethods(), я могу получить все методы из аннотации, и когда я использую только один, который начинается с annoProp, я могу использовать отражение и вызывать их, не так ли? Какой тип данных должен иметь? EDIT: Спасибо, я понял, и это работает! – CSchulz

+0

См. Редактирование в моем вопросе. Могу ли я исправить это, или я должен использовать @SuppresWarnings? – CSchulz

+0

@ H3llGhost: Не уверен, небрежно. 'Class.cast' * может * быть вашим другом ... –

Смежные вопросы