【问题标题】:Is it possible to read the value of a annotation in java?是否可以在java中读取注释的值?
【发布时间】:2010-11-28 13:16:38
【问题描述】:

这是我的代码:

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

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

【问题讨论】:

    标签: java annotations getter-setter java-6


    【解决方案1】:

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

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

    你可以这样做

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

    更新:获取私有字段使用

    Myclass.class.getDeclaredFields()
    

    【讨论】:

    • 我喜欢你的解决方案。我们如何使它更通用,而不是 MyClass 我想使用 T like for (Field f: T.class.getFields()) { Column column = f.getAnnotation(Column.class); if (column != null) System.out.println(column.columnName()); }
    • 没错!我也一直在努力弄清楚这一点。如果我想要一个不需要显式提供类名的注释处理器怎么办?是否可以从上下文中提取它; “这个”??
    • 我不确定我是否了解你们两个需要什么。请用一个完整的例子提出一个新问题。如果您愿意,可以在此处链接。
    • 使用Myclass.class.getDeclaredFields()获取私有字段
    • 它对我有用。谢谢。我正在寻找超类私有字段,所以我使用了 clsName.getSuperclass().getDeclaredFields()
    【解决方案2】:

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

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface TestAnnotation {
    
        String testText();
    }
    

    还有一个示例注释方法:

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

    另一个类中的示例方法打印 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());
        }
    }
    

    对于像你这样的字段注释没有太大的不同。

    干杯!

    【讨论】:

      【解决方案3】:

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

      一个已被删除的答案 (?) 提供了一个指向 an annotations tutorial 的有用链接,您可能会觉得有帮助;我已将链接复制到此处,以便人们使用它。

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

      【讨论】:

        【解决方案4】:

        详细说明@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());
        

        【讨论】:

        • Objects.nonNull 完全拥抱 Java 8 :) .filter(f -> nonNull(f.getAnnotation(Column.class)))
        【解决方案5】:

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

         Reflections reflections = new Reflections("my.project.prefix");
        
         Set<Field> ids = reflections.getFieldsAnnotatedWith(javax.persistence.Id.class);
        

        【讨论】:

          【解决方案6】:

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

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

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

          之后你可以这样做:

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

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

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

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

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

          【讨论】:

            【解决方案7】:

            在我的例子中,你也可以使用泛型类型,在你可以做类似的事情之前考虑到所有所说的:

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

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

            但可以做到这一点......

            【讨论】:

              【解决方案8】:

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

              对于下面的示例,我从具有 RequestMapping 注释的方法中提取 RequestMapping URL 值。 要使其适用于字段,只需更改

              for (Method method: clazz.getMethods())
              

              for (Field field: clazz.getFields())
              

              并将 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 "";
              }
              

              【讨论】:

                【解决方案9】:

                我使用它的一种方式:

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

                【讨论】:

                  猜你喜欢
                  • 2015-06-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-02-15
                  • 2019-02-08
                  相关资源
                  最近更新 更多