2009-04-10 14 views
15

Ho creato semplice annotazione in Javaannotazioni Java

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface Column { 
    String columnName(); 
} 

e la classe

public class Table { 

    @Column(columnName = "id") 
    private int colId; 

    @Column(columnName = "name") 
    private String colName; 

    private int noAnnotationHere; 

    public Table(int colId, String colName, int noAnnotationHere) { 
     this.colId = colId; 
     this.colName = colName; 
     this.noAnnotationHere = noAnnotationHere; 
    } 
} 

ho bisogno di iterare su tutti i campi, che sono annotati con Column e ottenere nome e valore di campo e annotazione. Ma ho problemi con il valore di ogni campo, poiché tutti sono di tipo diverso.

C'è qualcosa che restituisce la raccolta di campi che hanno certa annotazione ? Sono riuscito a farlo con questo codice, ma non penso che la riflessione sia un buon modo per risolverlo.

Table table = new Table(1, "test", 2); 

for (Field field : table.getClass().getDeclaredFields()) { 
    Column col; 
    // check if field has annotation 
    if ((col = field.getAnnotation(Column.class)) != null) { 
     String log = "colname: " + col.columnName() + "\n"; 
     log += "field name: " + field.getName() + "\n\n"; 

     // here i don't know how to get value of field, since all get methods 
     // are type specific 

     System.out.println(log); 
    } 
} 

Devo avvolgere ogni campo in oggetto, che implementare il metodo come getValue(), o c'è qualche modo migliore intorno a questo? Fondamentalmente tutto ciò di cui ho bisogno è la rappresentazione delle stringhe di ogni campo annotato.

modifica: sì field.get(table) funziona, ma solo per i campi public, esiste un modo per farlo anche per i campi private? O devo fare getter e in qualche modo, invocarlo?

+0

setAccessible. La versione dell'array sarà più veloce se si dispone di un gestore della sicurezza. setAccessible è, ovviamente, molto pericoloso nelle situazioni in cui si dispone di un gestore della sicurezza. –

+0

spaventoso ...sembra che tu stia implementando la tua versione di JPA – basszero

+0

@basszero: hai ragione, devo farlo per il mio progetto universitario a causa della mia stupida insegnante che vive in una grotta e non permette l'uso di alcuna libreria come Toplink ecc ... –

risposta

11

Ogni oggetto deve avere toString() definito. (E puoi sovrascrivere questo per ogni classe per ottenere una rappresentazione più significativa).

Quindi dove il vostro "// qui non lo so" commento è, si potrebbe avere:

Object value = field.get(table); 
// gets the value of this field for the instance 'table' 

log += "value: " + value + "\n"; 
// implicitly uses toString for you 
// or will put 'null' if the object is null 
+0

thx, funziona, ma solo se i campi sono dichiarati come pubblici, quando sono privati ​​ottengo Eccezione nel thread "main" java.lang.IllegalAccessException: Class Main non può accedere a un membro della classe Table con i modificatori "private" –

+0

@Darth - dai un'occhiata a Field.setAccessible - http://java.sun.com/javase/6/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) – McDowell

+0

@McDowell - thx che risolve il problema –

9

riflessione è esattamente il modo per risolverlo. Trovare le cose sui tipi e sui loro membri al momento dell'esecuzione è praticamente la definizione di riflessione! Il modo in cui l'hai fatto sembra a posto.

per trovare il valore del campo, utilizzare field.get(table)

4

riflessione è esattamente il modo di guardare le annotazioni. Sono una forma di "metadati" allegata alla classe o al metodo e le annotazioni Java sono state progettate per essere esaminate in questo modo.

+0

Wow, condivido le stesse prime 5 parole con la risposta di Jon, devo migliorare :) – Uri

+2

Se guardi da vicino vedrai che il signor Skeet ha piazzato la sua terza parola "esattamente" 'in corsivo mentre la voce è solo nella normale formattazione non italica. Ben fatto per un passo nella giusta direzione, ma senza questa enfasi sottile ma così descrittiva che Jon ha usato le tue prime cinque parole non è ancora riuscita a onorare Skeets. –

2

Reflection è un modo per elaborare l'oggetto (probabilmente l'unico modo se i campi sono privati ​​e non hanno alcun tipo di metodo di accesso). Avrai bisogno di guardare Field.setAccessible e forse Field.getType.

Un altro approccio è generare un'altra classe per enumerare i campi annotati utilizzando un compile-time annotation processor. Ciò richiede un'API com.sun in Java 5, ma il supporto è migliore nel JDK Java 6 (IDE come Eclipse potrebbero richiedere una configurazione speciale del progetto).

Problemi correlati