是否可以在java中读取注释的值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4296910/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 15:30:26  来源:igfitidea点击:

Is it possible to read the value of a annotation in java?

javaannotationsgetter-setterjava-6

提问by BeeS

this is my code:

这是我的代码:

@Column(columnName="firstname")


private String firstName;

 @Column(columnName="lastname")
 private String lastName;

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

is it possible to read the value of my annotation @Column(columnName="xyz123") in another class?

是否可以在另一个类中读取我的注释 @Column( columnName="xyz123")的值?

回答by T.J. Crowder

I've never done it, but it looks like Reflectionprovides this. Fieldis an AnnotatedElementand so it has getAnnotation. This pagehas an example (copied below); quite straightforward if you know the class of the annotation and if the annotation policy retains the annotation at runtime. Naturally if the retention policy doesn't keep the annotation at runtime, you won't be able to query it at runtime.

我从来没有做过,但看起来Reflection提供了这个。FieldAnnotatedElement,所以它有getAnnotation这个页面有一个例子(复制如下);如果您知道注释的类并且注释策略在运行时保留注释,则非常简单。自然地,如果保留策略在运行时不保留注释,您将无法在运行时查询它。

An answer that's since been deleted (?) provided a useful link to an annotations tutorialthat you may find helpful; I've copied the link here so people can use it.

此后已删除的答案 (?) 提供了指向注释教程的有用链接,您可能会发现它很有帮助;我已将链接复制到此处,以便人们可以使用它。

Example from this page:

此页面的示例:

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
  String str();

  int val();
}

class Meta {
  @MyAnno(str = "Two Parameters", val = 19)
  public static void myMeth(String str, int i) {
    Meta ob = new Meta();

    try {
      Class c = ob.getClass();

      Method m = c.getMethod("myMeth", String.class, int.class);

      MyAnno anno = m.getAnnotation(MyAnno.class);

      System.out.println(anno.str() + " " + anno.val());
    } catch (NoSuchMethodException exc) {
      System.out.println("Method Not Found.");
    }
  }

  public static void main(String args[]) {
    myMeth("test", 10);
  }
}

回答by Cephalopod

Yes, if your Column annotation has the runtime retention

是的,如果您的 Column 注释具有运行时保留

@Retention(RetentionPolicy.RUNTIME)
@interface Column {
    ....
}

you can do something like this

你可以做这样的事情

for (Field f: MyClass.class.getFields()) {
   Column column = f.getAnnotation(Column.class);
   if (column != null)
       System.out.println(column.columnName());
}

UPDATE : To get private fields use

更新:要使用私有字段

Myclass.class.getDeclaredFields()

回答by Lachezar Balev

Of course it is. Here is a sample annotation:

当然是这样。这是一个示例注释:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {

    String testText();
}

And a sample annotated method:

和一个示例注释方法:

class TestClass {

    @TestAnnotation(testText="zyx")
    public void doSomething() {}
}

And a sample method in another class that prints the value of the testText:

另一个类中的示例方法打印 testText 的值:

Method[] methods = TestClass.class.getMethods();
for (Method m : methods) {
    if (m.isAnnotationPresent(TestAnnotation.class)) {
        TestAnnotation ta = m.getAnnotation(TestAnnotation.class);
        System.out.println(ta.testText());
    }
}

Not much different for field annotations like yours.

像您这样的字段注释没有太大不同。

Cheerz!

干杯!

回答by Fritz Duchardt

While all the answers given so far are perfectly valid, one should also keep in mind the google reflections libraryfor a more generic and easy approach to annotation scanning, e.g.

虽然到目前为止给出的所有答案都是完全有效的,但还应该记住谷歌反射库,以获得更通用和更简单的注释扫描方法,例如

 Reflections reflections = new Reflections("my.project.prefix");

 Set<Field> ids = reflections.getFieldsAnnotatedWith(javax.persistence.Id.class);

回答by SigmaSoldier

You can also use generic types, in my case, taking into account everything said before you can do something like:

在我的情况下,您还可以使用泛型类型,在您可以执行以下操作之前考虑到所有内容:

public class SomeTypeManager<T> {

    public SomeTypeManager(T someGeneric) {

        //That's how you can achieve all previously said, with generic types.
        Annotation[] an = someGeneric.getClass().getAnnotations();

    }

}

Remember, that this will not equival at 100% to SomeClass.class.get(...)();

请记住,这不会 100% 等价于 SomeClass.class.get(...)();

But can do the trick...

但可以做的伎俩...

回答by Simon Baars

Elaborating to the answer of @Cephalopod, if you wanted all column names in a list you could use this oneliner:

详细说明@Cephalopod 的答案,如果你想要一个列表中的所有列名,你可以使用这个 oneliner:

List<String> columns = 
        Arrays.asList(MyClass.class.getFields())
              .stream()
              .filter(f -> f.getAnnotation(Column.class)!=null)
              .map(f -> f.getAnnotation(Column.class).columnName())
              .collect(Collectors.toList());

回答by Oleg Poltoratskii

In common case you have privateaccess for fields, so you CAN'T use getFieldsin reflection. Instead of this you should use getDeclaredFields

通常情况下,您对字段具有私有访问权限,因此您不能在反射中使用getFields。而不是这个,你应该使用getDeclaredFields

So, firstly, you should be aware if your Column annotation has the runtime retention:

因此,首先,您应该知道您的 Column 注释是否具有运行时保留:

@Retention(RetentionPolicy.RUNTIME)
@interface Column {
}

After that you can do something like this:

之后,您可以执行以下操作:

for (Field f: MyClass.class.getDeclaredFields()) {
   Column column = f.getAnnotation(Column.class);
       // ...
}

Obviously, you would like to do something with field - set new value using annotation value:

显然,您想对字段做一些事情 - 使用注释值设置新值:

Column annotation = f.getAnnotation(Column.class);
if (annotation != null) {
    new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
        object,
        myCoolProcessing(
            annotation.value()
        )
    );
}

So, full code can be looked like this:

所以,完整的代码可以是这样的:

for (Field f : MyClass.class.getDeclaredFields()) {
    Column annotation = f.getAnnotation(Column.class);
    if (annotation != null)
        new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
                object,
                myCoolProcessing(
                        annotation.value()
                )
        );
}

回答by MattWeiler

For the few people asking for a generic method, this should help you (5 years later :p).

对于少数要求通用方法的人,这应该对您有所帮助(5 年后:p)。

For my below example, I'm pulling the RequestMapping URL value from methods that have the RequestMapping annotation. To adapt this for fields, just change the

对于下面的示例,我从具有 RequestMapping 注释的方法中提取 RequestMapping URL 值。为了适应这个领域,只需改变

for (Method method: clazz.getMethods())

to

for (Field field: clazz.getFields())

And swap usage of RequestMappingfor whatever annotation you are looking to read. But make sure that the annotation has @Retention(RetentionPolicy.RUNTIME).

并为您要阅读的任何注释交换RequestMapping 的使用。但请确保注释具有@Retention(RetentionPolicy.RUNTIME)

public static String getRequestMappingUrl(final Class<?> clazz, final String methodName)
{
    // Only continue if the method name is not empty.
    if ((methodName != null) && (methodName.trim().length() > 0))
    {
        RequestMapping tmpRequestMapping;
        String[] tmpValues;

        // Loop over all methods in the class.
        for (Method method: clazz.getMethods())
        {
            // If the current method name matches the expected method name, then keep going.
            if (methodName.equalsIgnoreCase(method.getName()))
            {
                // Try to extract the RequestMapping annotation from the current method.
                tmpRequestMapping = method.getAnnotation(RequestMapping.class);

                // Only continue if the current method has the RequestMapping annotation.
                if (tmpRequestMapping != null)
                {
                    // Extract the values from the RequestMapping annotation.
                    tmpValues = tmpRequestMapping.value();

                    // Only continue if there are values.
                    if ((tmpValues != null) && (tmpValues.length > 0))
                    {
                        // Return the 1st value.
                        return tmpValues[0];
                    }
                }
            }
        }
    }

    // Since no value was returned, log it and return an empty string.
    logger.error("Failed to find RequestMapping annotation value for method: " + methodName);

    return "";
}

回答by R K Punjal

one of the ways I used it :

我使用它的方法之一:

protected List<Field> getFieldsWithJsonView(Class sourceClass, Class jsonViewName){
    List<Field> fields = new ArrayList<>();
    for (Field field : sourceClass.getDeclaredFields()) {
        JsonView jsonViewAnnotation = field.getDeclaredAnnotation(JsonView.class);
        if(jsonViewAnnotation!=null){
            boolean jsonViewPresent = false;
            Class[] viewNames = jsonViewAnnotation.value();
            if(jsonViewName!=null && Arrays.asList(viewNames).contains(jsonViewName) ){
                fields.add(field);
            }
        }
    }
    return fields;
}