2017-02-28 12 views
10

Dường như không thể truy cập chú thích TYPE_USE thông qua phản ánh khi loại chú thích là giao diện chung, lồng nhau.Chú thích TYPE_USE bị mất khi loại được lồng vào nhau, giao diện chung

hãy quan sát ví dụ sau:

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 
import java.lang.reflect.AnnotatedType; 
import java.lang.reflect.Method; 
import java.util.Arrays; 
import java.util.Map; 
import java.util.Map.Entry; 

public class LostAnnotation { 
    @Retention(RetentionPolicy.RUNTIME) 
    @Target(ElementType.TYPE_USE) 
    public @interface SomeTypeAnnotation { 
    } 

    @SomeTypeAnnotation Map<String, String> map; 
    @SomeTypeAnnotation Entry<String, String> entry; 

    public static @SomeTypeAnnotation Entry<String, String> someMethod(
     @SomeTypeAnnotation Map<String, String> map, 
     @SomeTypeAnnotation Entry<String, String> entry) { 
    return null; 
    } 

    public static void main(String[] args) throws Exception { 
    Class<LostAnnotation> clazz = LostAnnotation.class; 
    Method method = clazz.getMethod("someMethod", Map.class, Entry.class); 
    AnnotatedType[] types = method.getAnnotatedParameterTypes(); 

    print("map field", clazz.getDeclaredField("map").getAnnotatedType()); 
    print("map parameter", types[0]); 

    print("entry field", clazz.getDeclaredField("entry").getAnnotatedType()); 
    print("entry parameter", types[1]); 
    print("entry return type", method.getAnnotatedReturnType()); 
    } 

    static void print(String title, AnnotatedType type) { 
    System.out.printf("%s: %s%n", title, Arrays.asList(type.getAnnotations())); 
    } 
} 

Các dự kiến ​​sản lượng của mã trên là

map field: [@LostAnnotation$SomeTypeAnnotation()] 
map parameter: [@LostAnnotation$SomeTypeAnnotation()] 
entry field: [@LostAnnotation$SomeTypeAnnotation()] 
entry parameter: [@LostAnnotation$SomeTypeAnnotation()] 
entry return type: [@LostAnnotation$SomeTypeAnnotation()] 

Tuy nhiên, thực tế sản lượng của mã trên là

map field: [@LostAnnotation$SomeTypeAnnotation()] 
map parameter: [@LostAnnotation$SomeTypeAnnotation()] 
entry field: [] 
entry parameter: [] 
entry return type: [] 

Chú thích được truy xuất chính xác từ mọi giao diện sử dụng của giao diện Map. Tuy nhiên, trên mọi giao diện sử dụng của giao diện Entry, có thể là trường, kiểu trả về hoặc tham số, chú thích bị mất. Giải thích duy nhất mà tôi có cho giao diện này là giao diện Entryđược lồng bên trong giao diện Map.

Tôi đã chạy ví dụ trên trên JDK oracle mới nhất (8u121) trên win64. Tôi có làm gì sai hay đây có phải là lỗi không?

Chú thích của tôi được lồng để dễ đọc. Làm cho nó một giao diện cấp cao nhất không thay đổi bất cứ điều gì.

+2

Tôi đã thử nghiệm và phát xung quanh bằng mã của bạn và không thể tìm thấy bất kỳ lỗi nào trong mã của bạn từ phía bạn. Vì vậy, tôi đồng ý với kriegaex, đường nối này là một lỗi trong jvm. –

Trả lời

5

này đã được đã được phát hiện trong SO: Why annotation on generic type argument is not visible for nested type?

Câu trả lời được lỗi đã được đệ trình nhưng trong ưu tiên thấp hơn như những trường hợp không xuất hiện thường xuyên.

Tuy nhiên, bạn có thể sử dụng ByteBuddy để phân tích cú pháp bytecode và truy xuất loại chú thích.

ASM cũng hoạt động, theo kinh nghiệm của tôi và tôi nghi ngờ bất kỳ trình phân tích cú pháp bytecode nào cũng sẽ khắc phục lỗi này.

0

Tôi không biết liệu tôi có phải là nguồn đáng tin cậy hay không (chắc chắn không phải là nguồn chính thức), nhưng IMO đây là lỗi hoặc ít nhất là thiếu sót (không được triển khai đầy đủ) trong JDK.

Bạn không làm gì sai - hoặc cả hai chúng tôi đều sai, vẫn là một khả năng.

Như Bertrand Russell nói:

Thực tế là một ý kiến ​​đã được tổ chức rộng rãi là không có bằng chứng gì mà nó không phải là hoàn toàn vô lý.

;-)

Các vấn đề liên quan