使用Java Annotations访问类属性的值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Java Annotations访问类属性的值相关的知识,希望对你有一定的参考价值。

我正在使用注释的java示例,我使用注释创建了一个简单的POJO(java bean)到它的属性。我希望能够创建此类型的新对象,并使用创建的注释检索其属性的值。

我的POJO:

import java.io.Serializable;

import annotations.BusinessObject;
import annotations.BusinessObjectAttribute;
import annotations.BusinessObjectName;
import annotations.BusinessObjectPolicy;
import annotations.BusinessObjectRevision;
import annotations.BusinessObjectVault;

@BusinessObject
public class IndusTask implements Serializable{

/**
 * 
 */
private static final long serialVersionUID = 1L;


// Mandatory to create new object !
@BusinessObjectName
private String taskName;
@BusinessObjectRevision
private String taskRevision;
@BusinessObjectVault
private String vault;
// Mandatory to invoke iTask.create(context, policy) in Database
@BusinessObjectPolicy
private String policy;

//Specific attributes
@BusinessObjectAttribute
private String taskDescription;
@BusinessObjectAttribute
private String creationDate;
@BusinessObjectAttribute
private Integer weight;

public IndusTask() {
}

public IndusTask(String taskName, String taskRevision, String vault, String policy, String taskDescription,
        String creationDate, Integer weight) {
    super();
    this.taskName = taskName;
    this.taskRevision = taskRevision;
    this.vault = vault;
    this.policy = policy;
    this.taskDescription = taskDescription;
    this.creationDate = creationDate;
    this.weight = weight;
}

public String getTaskName() {
    return taskName;
}

public void setTaskName(String taskName) {
    this.taskName = taskName;
}

public String getTaskRevision() {
    return taskRevision;
}

public void setTaskRevision(String taskRevision) {
    this.taskRevision = taskRevision;
}

public String getVault() {
    return vault;
}

public void setVault(String vault) {
    this.vault = vault;
}

public String getTaskDescription() {
    return taskDescription;
}

public void setTaskDescription(String taskDescription) {
    this.taskDescription = taskDescription;
}

public String getCreationDate() {
    return this.creationDate;
}

public void setCreationDate(String creationDate) {
    this.creationDate = creationDate;
}

public Integer getWeight() {
    return weight;
}

public void setWeight(Integer weight) {
    this.weight = weight;
}

public String getPolicy() {
    return policy;
}

public void setPolicy(String policy) {
    this.policy = policy;
}

}

属性声明的示例:*业务对象类型声明

package annotations;

import java.lang.annotation.*;

//@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface BusinessObject {

}

*业务对象名称属性:

package annotations;

import java.lang.annotation.*;

//@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BusinessObjectName {

}

我创建了一个main来测试是否检测到所有注释:

public class MainImpl {

    public static void main(String[] args) {
        // TODO Auto-generated method stub


        IndusTask myTask = new IndusTask("mytstTask", "001", "eService Production", "TstTask Process",
                "myTstTask Description", "2018/02/16@15:30:10:GMT", 200);

        System.out.println(myTask.getClass().getAnnotations().length);

    }

}

输出显示1!所以只检测到第一个注释!

我还被告知可以使用这些注释(类似于)来访问对象属性值:

object.getClass().getAnnotations()

我能怎么做 ?

答案

您需要迭代字段,获取注释并在注释匹配的任何位置设置值(它可以匹配多个字段):

@Retention(RetentionPolicy.RUNTIME)
public @interface Field1 {}

@Retention(RetentionPolicy.RUNTIME)
public @interface Field2 {}

public static class UnderTest {

    @Field1
    private String field1;

    @Field2
    private int field2;

    public UnderTest(String field1, int field2) {
        this.field1 = field1;
        this.field2 = field2;
    }

    @Override
    public String toString() {
        return field1 + "=" + field2;
    }
}

public static void setter(Object obj, Class<? extends Annotation> fieldAnnotation, Object fieldValue) throws IllegalAccessException {
    for (Field field: obj.getClass().getDeclaredFields()) {
        for (Annotation annot: field.getDeclaredAnnotations()) {
            if (annot.annotationType().isAssignableFrom(fieldAnnotation)) {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                field.set(obj, fieldValue);
            }
        }
    }
}

public static void main(String[] argv) throws IllegalAccessException {
    UnderTest underTest = new UnderTest("A", 1);
    System.out.println(underTest);

    setter(underTest, Field1.class, "B");
    setter(underTest, Field2.class, 2);
    System.out.println(underTest);
}

运行此打印

A = 1

B = 2

另一答案

听起来你也是在田野上的注释之后?

例如。对于第一个私人领域:

myTask.getClass().getDeclaredFields()[0].getAnnotations()

请注意,根据您访问私有字段的方式,有时您还需要首先确保它可以访问:

...getDeclaredFields()[0].setAccessible(true);

[edit]这些值也可以从字段中获得。一个基本的工作示例:

for (Field f : myTask.getClass().getDeclaredFields()) {
    f.setAccessible(true);
    System.out.println(f.getName() + "=" + f.get(myTask));  
    System.out.println("  annotations=" + java.util.Arrays.toString(f.getAnnotations()));   
}

以上是关于使用Java Annotations访问类属性的值的主要内容,如果未能解决你的问题,请参考以下文章

java中静态属性和静态方法的问题

是否有工具可以使用 Room Annotations 自动生成 Android POJO 类

使用属性升级Mybank

说说对java反射的理解,使用反射如何获取一个类的所有方法,使用反射需要注意哪些问题?

Java Annotations 和 C# Attributes 有啥异同?

不得不会的10点Java基础知识