Java注解

15

我已经在Java中创建了简单的注释。

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

以及类

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

我需要遍历所有带有Column注解的字段,并获取字段和注解的名称。但是我在获取每个字段的时遇到了问题,因为它们都是不同的数据类型
是否有任何方法可以返回具有特定注解的字段集合? 我已经使用了以下代码来实现,但我认为反射并不是解决这个问题的好方法。
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);
    }
}

我需要在每个字段中包装一个对象,该对象实现类似于getValue()的方法,还是有更好的解决方法?基本上,我只需要每个带注释的字段的字符串表示形式。
编辑:是的field.get(table)可以工作,但仅适用于public字段,是否有任何方法可以即使对于private字段也能够做到这一点?还是我必须创建getter并以某种方式调用它?

setAccessible。如果您有安全管理器,数组版本将更快。当然,在存在安全管理器的情况下,setAccessible在某些情况下非常危险。 - Tom Hawtin - tackline
看起来有点可怕...你似乎正在实现自己的JPA版本。 - basszero
@basszero:没错,我必须为我的大学项目做这个,因为我的愚蠢老师住在山洞里,不允许使用任何库,比如Toplink等... - Jakub Arnold
4个回答

11
每个对象都应该定义toString()方法。(你可以为每个类覆盖此方法,以获得更有意义的表示。)
所以在你的"// here I don't know"注释处,你可以这样写:
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

谢谢,这个可以工作,但只有当字段被声明为public时才有效,当它们是private时,我会得到以下异常信息:Exception in thread "main" java.lang.IllegalAccessException: Class Main can not access a member of class Table with modifiers "private"。 - Jakub Arnold
@Darth - 请看一下Field.setAccessible - http://java.sun.com/javase/6/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible(boolean) - McDowell

9

反射是解决这个问题的唯一方法。在执行时查找类型及其成员的信息几乎就是反射的定义!您所做的方式看起来很好。

要查找字段的值,请使用field.get(table)


4

反射是查看注释的方法,它们是附加到类或方法上的一种“元数据”,Java注释就是为了以这种方式进行检查而设计的。


哇,我和Jon的答案有相同的前5个单词,我一定在进步 :) - Uri
2
如果你仔细看,你会发现Skeet先生将他的第三个单词“exactly”用斜体字标注了,而你的输入只有普通的非斜体格式。很好,你已经朝着正确的方向迈出了一步,但是没有像Jon那样使用这种微妙但如此描述性的强调,你的前五个单词仍然不及Skeet先生的。 - Howard May

2

反射是处理对象的一种方式(如果字段是私有的并且没有任何类型的访问器方法,则可能是唯一的方式)。您需要查看Field.setAccessible和可能的Field.getType

另一种方法是使用编译时注解处理器为枚举注释字段生成另一个类。这需要Java 5中的com.sun API,但在Java 6 JDK中支持更好(IDE如Eclipse可能需要特殊项目配置)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接