Có thể đọc giá trị của chú thích trong java không?


98

đây là mã của tôi:

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

có thể đọc giá trị của chú thích @Column ( columnName = "xyz123") của tôi trong một lớp khác không?

Câu trả lời:


122

Có, nếu chú thích Cột của bạn có lưu giữ thời gian chạy

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

bạn có thể làm một cái gì đó như thế này

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

CẬP NHẬT: Để sử dụng các trường riêng tư

Myclass.class.getDeclaredFields()

1
tôi thích giải pháp của bạn. Làm thế nào chúng ta có thể làm cho nó chung chung hơn thay vì MyClass mà tôi muốn sử dụng T like for (Field f: T.class.getFields ()) {Column column = f.getAnnotation (Column.class); if (column! = null) System.out.println (column.columnName ()); }
ATHER

1
Chính xác! Tôi cũng đã đấu tranh để tìm ra điều đó. Điều gì sẽ xảy ra nếu tôi muốn có một bộ xử lý chú thích không cần được cung cấp tên lớp một cách rõ ràng? Nó có thể được thực hiện để chọn nó từ bối cảnh; 'điều này'??
5122014009

Tôi không chắc mình hiểu hai người cần gì. Vui lòng hỏi đó như một câu hỏi mới với đầy đủ ví dụ. Bạn có thể liên kết nó ở đây nếu bạn muốn.
Cephalopod

3
Sử dụng Myclass.class.getDeclaredFields()để có được lĩnh vực tư nhân
q0re

Nó đã làm việc cho tôi. cảm ơn. . Tôi đang tìm kiếm các lĩnh vực tin cha vì vậy tôi sử dụng clsName.getSuperclass () getDeclaredFields ()
Shashank

88

Tất nhiên là thế rồi. Đây là một chú thích mẫu:

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

    String testText();
}

Và một phương pháp chú thích mẫu:

class TestClass {

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

Và một phương thức mẫu trong một lớp khác in ra giá trị của 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());
    }
}

Không khác nhiều đối với các chú thích trường như của bạn.

Cheerz!


21

Tôi chưa bao giờ làm điều đó, nhưng có vẻ như Reflection cung cấp điều này. Fieldlà một AnnotatedElementvà vì vậy nó có getAnnotation. Trang này có một ví dụ (được sao chép bên dưới); khá đơn giản nếu bạn biết lớp của chú thích và nếu chính sách chú thích giữ lại chú thích trong thời gian chạy. Đương nhiên nếu chính sách lưu giữ không giữ chú thích trong thời gian chạy, bạn sẽ không thể truy vấn chú thích đó trong thời gian chạy.

Một câu trả lời đã bị xóa (?) Đã cung cấp một liên kết hữu ích đến hướng dẫn chú thích mà bạn có thể thấy hữu ích; Tôi đã sao chép liên kết ở đây để mọi người có thể sử dụng nó.

Ví dụ từ trang này :

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

6

Xây dựng câu trả lời của @Cephalopod, nếu bạn muốn tất cả các tên cột trong danh sách, bạn có thể sử dụng oneliner này:

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 để hoàn toàn nắm lấy Java 8 :) .filter (f -> nonNull (f.getAnnotation (Column.class)))
dehumanizer

4

Mặc dù tất cả các câu trả lời được đưa ra cho đến nay đều hoàn toàn hợp lệ, nhưng bạn cũng nên nhớ thư viện phản ánh của google để có cách tiếp cận chung chung và dễ dàng hơn đối với việc quét chú thích, ví dụ:

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

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

3

Bạn cũng có thể sử dụng các loại chung chung, trong trường hợp của tôi, có tính đến mọi thứ đã nói trước khi bạn có thể làm điều gì đó như:

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

    }

}

Hãy nhớ rằng điều này sẽ không tương đương 100% với SomeClass.class.get (...) ();

Nhưng có thể làm được thủ thuật ...


3

Trong trường hợp phổ biến, bạn có quyền truy cập riêng tư cho các trường, vì vậy bạn KHÔNG THỂ sử dụng getFields trong phản chiếu. Thay vì điều này, bạn nên sử dụng getDeclaredFields

Vì vậy, trước tiên, bạn nên biết liệu chú thích Cột của bạn có lưu giữ thời gian chạy hay không:

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

Sau đó, bạn có thể làm điều gì đó như sau:

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

Rõ ràng, bạn muốn làm điều gì đó với trường - đặt giá trị mới bằng cách sử dụng giá trị chú thích:

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

Vì vậy, mã đầy đủ có thể trông như thế này:

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

2

Đối với một số ít người yêu cầu một phương pháp chung, điều này sẽ giúp bạn (5 năm sau: p).

Đối với ví dụ dưới đây, tôi đang lấy giá trị URL RequestMapping từ các phương thức có chú thích RequestMapping. Để điều chỉnh điều này cho các trường, chỉ cần thay đổi

for (Method method: clazz.getMethods())

đến

for (Field field: clazz.getFields())

Và hoán đổi việc sử dụng RequestMapping cho bất kỳ chú thích nào bạn đang muốn đọc. Nhưng hãy đảm bảo rằng chú thích có @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 "";
}

0

một trong những cách tôi đã sử dụng:

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;
}    
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.