2009-04-10 18 views
15

que he creado en Java simple anotaciónanotaciones Java

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

y la clase

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; 
    } 
} 

necesito iterar sobre todos los campos, que están anotados con Column y obtener nombre y valor de campo y anotación. Pero tengo un problema al obtener el valor de cada campo, ya que todos ellos son de tipo de datos .

¿Hay algo que devuelva la colección de campos que tienen cierta anotación ? Pude hacerlo con este código, pero no creo que esa reflexión sea una buena forma de resolverlo.

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); 
    } 
} 

¿Tengo que envolver cada campo en el objeto, lo que pondría en práctica el método como getValue(), o hay alguna forma mejor de evitar esto? Básicamente, todo lo que necesito es una representación de cadena de cada campo anotado.

editar: yep field.get(table) funciona, pero solo para los campos public, ¿hay alguna forma de hacerlo incluso para los campos private? ¿O tengo que hacer getter y de alguna manera invocarlo?

+0

setAccessible. La versión de matriz será más rápida si tiene un administrador de seguridad presente. setAccessible es, por supuesto, muy peligroso en situaciones donde tienes administrador de seguridad. –

+0

miedo ...Parece que estás implementando tu propia versión de JPA – basszero

+0

@basszero: sí, tienes razón, tengo que hacer esto para mi proyecto de universidad debido a mi estúpido maestro que vive en una cueva y no permite el uso de ninguna biblioteca como Toplink etc ... –

Respuesta

11

Cada objeto debe tener toString() definido. (Y puede anular esto para cada clase para obtener una representación más significativa).

Así que dónde está su "// aquí no sé" comentario es, usted podría tener:

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, esto funciona, pero solo si los campos se declaran como públicos, cuando son privados obtengo Excepción en el hilo "principal" java.lang.IllegalAccessException: Class Main no puede acceder a un miembro de la clase Table con modificadores "privados" –

+0

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

+0

@McDowell - thx que resuelve el problema –

9

La reflexión es exactamente la forma de resolverlo. ¡Descubrir cosas sobre los tipos y sus miembros en tiempo de ejecución es más o menos la definición de reflexión! La forma en que lo has hecho me parece bien.

Para hallar el valor del campo, utilice field.get(table)

4

La reflexión es exactamente la manera de mirar las anotaciones. Son una forma de "metadatos" adjunta a la clase o método, y las anotaciones de Java se diseñaron para examinarse de esa manera.

+0

Wow, comparto las primeras 5 palabras con la respuesta de Jon, debo estar mejorando :) – Uri

+2

Si miras de cerca verás que el Sr. Skeet había colocado su tercera palabra exactamente 'en cursiva mientras su entrada solo está en formato regular sin cursiva. Bien hecho para dar un paso en la dirección correcta, pero sin este énfasis sutil pero tan descriptivo que Jon ha usado sus primeras cinco palabras aún no está a la altura de Mr Skeets. –

2

La reflexión es una forma de procesar el objeto (probablemente sea la única manera si los campos son privados y no tienen ningún tipo de método de acceso). Tendrá que mirar Field.setAccessible y quizás Field.getType.

Otro enfoque es generar otra clase para enumerar los campos anotados utilizando un compile-time annotation processor. Esto requiere una API de com.sun en Java 5, pero el soporte es mejor en Java 6 JDK (IDE como Eclipse puede requerir una configuración de proyecto especial).

Cuestiones relacionadas