2012-11-26 9 views
19

Kann Annotation komplexe Rückgabetyp, wie HashMap.Kann Java-Annotation haben komplexe Rückgabetyp wie HashMap

Ich suche so etwas wie:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface column { 
    public HashMap<String, String> table(); 
} 

so kann ich eine Konstante wie (Pseudo-Code) kommentiert haben:

@column({table=(dbName, tableName), table=(dbName, tableName2)}) 
public static final String USER_ID = "userid"; 

Wenn Annotation nicht zulässt Komplex haben Rückgabetyp, dann irgendeine gute Praxis für diese Art von Fall?

+0

ausgezeichnete Frage .. –

Antwort

48

Nein, Anmerkungselemente können nur primitive Typen, Strings, enum Typen, Class, andere Annotationen oder Arrays von diesen sein. Der typische Weg, um diese Arten von Strukturen darzustellen wäre eine andere Annotationstyp

public @interface TableMapping { 
    public String dbName(); 
    public String tableName(); 
} 

dann

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface column { 
    public TableMapping[] table(); 
} 

sagen zu erklären und die Anmerkung als

@column(table={ 
    @TableMapping(dbName="dbName", tableName="tableName"), 
    @TableMapping(dbName="db2", tableName="table2") 
}) 
public String userId = "userid"; 
+1

Vergessen Sie nicht, Aufzählungen und Klassen –

+0

@ AleksanderBlomskøld guter Punkt, danke. –

+0

@IanRoberts Ich habe etwas Ähnliches gemacht, es ist ein bisschen ärgerlich, wenn Sie nur @table verwenden, auch wenn ein Teil der Spalte nur ein TableMapping hat, muss @ table zusammen mit einem @ TableMapping haben. Wenn Sie @ table für Felder mit mehr als einem Tabellemapping verwenden, während Sie @ TableMapping für die Spalten mit nur einem Tabellemapping verwenden. Aber der letztere Fall wird eine komplexere Methode zum Abrufen z. getColumnsInTableA(). – Shengjie

3

Ein paar Jahre später verwenden bringt us Java 8. Es bietet eine Möglichkeit, Anmerkungen der gleichen Klasse zu wiederholen.

In Java 8 können Sie eine Annotation deklarieren, die implizit in eine Containeranmerkung eingeschlossen wird. Sie geben als @Repeated(value=a_class) eine Annotation an, die wiederholbar sein soll. Wenn Sie mehrere Instanzen einer wiederholbaren Annotation hinzufügen, wird der Compiler diese automatisch in die als Argument angegebene Container-Annotation a_class umbrechen (@Repeated).

Wenn Sie erklären:

@Retention(RetentionPolicy.RUNTIME) 
public @interface Columns { 
    Column[] value() default {}; 
} 

@Retention(RetentionPolicy.RUNTIME) 
@Repeatable(value = Columns.class) 
public @interface Column { 
    String dbName(); 
    String tableName(); 
} 

dann können Sie die Anmerkung mehrfach verwenden, mit oder ohne sie in einer anderen Anmerkung Einwickeln, beide sind gleichwertig:

@Column(dbName="db1", tableName="table1") 
@Column(dbName="db2", tableName="table2") 
public static final String USER_ID = "userid"; 

@Columns({ 
     @Column(dbName="db3", tableName="table3"), 
     @Column(dbName="db4", tableName="table4") 
}) 
public static final String LAST_NAME = "last name"; 

Die Anmerkungen abgerufen werden unter Verwendung getAnnotationsByType(class) in beide Fälle.

public static void main(String[] args) { 
    for(Field field : AnnotationsTest.class.getDeclaredFields()){ 
     System.out.println("Field: " + field.getName()); 
     Column[] columns = field.getAnnotationsByType(Column.class); 
     for(Column column : columns){ 
      System.out.println(" db: " + column.dbName() + " table: " + column.tableName()); 
     } 
     System.out.println(); 
    } 
} 

Es sollte Ausgabe:

Field: USER_ID 
    db: db1 table: table1 
    db: db2 table: table2 

Field: LAST_NAME 
    db: db3 table: table3 
    db: db4 table: table4 
Verwandte Themen