views:

999

answers:

5
+2  Q: 

Java annotations

I've created simple annotation in Java

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

and class

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

I need to iterate over all fields, that are annotated with Column and get name and value of field and annotation. But I've got problem with getting value of each field, since all of them are of different data type.

Is there anything that would return collection of fields that have certain annotation? I managed to do it with this code, but I don't think that reflection is good way to solve it.

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

Do I have to wrap every field in object, which would implement method like getValue(), or is there some better way around this? Basicly all I need is string representation of each field that is annotated.

edit: yep field.get(table) works, but only for public fields, is there any way how to do this even for private fields? Or do I have to make getter and somehow invoke it?

+3  A: 

Every object should has toString() defined. (And you can override this for each class to get a more meaningful representation).

So you where your "// here I don't know" comment is, you could have:

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
kenj0418
thx, this works, but only if fields are declared as public, when they're private i get Exception in thread "main" java.lang.IllegalAccessException: Class Main can not access a member of class Table with modifiers "private"
Darth
@Darth - have a look at Field.setAccessible - http://java.sun.com/javase/6/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible(boolean)
McDowell
@McDowell - thx that solves the problem
Darth
+2  A: 

Reflection is exactly the way to solve it. Finding out things about types and their members at execution time is pretty much the definition of reflection! The way you've done it looks fine to me.

To find the value of the field, use field.get(table)

Jon Skeet
+1  A: 

Reflection is exactly the way to look at annotations. They are a form of "metadata" attached to the class or method, and Java annotations were designed to be examined that way.

Uri
Wow, I share the same first 5 words with Jon's answer, I must be improving :)
Uri
A: 

Reflection is one way to process the object (probably the only way if the fields are private and don't have any kind of accessor method). You'll need to look at Field.setAccessible and perhaps Field.getType.

Another approach is to generate another class for enumerating the annotated fields using a compile-time annotation processor. This requires a com.sun API in Java 5, but support is better in the Java 6 JDK (IDEs like Eclipse may require special project configuration).

McDowell
A: 

Why not use commons-beanutils to do the getter based get?

Nik