Làm thế nào để các chính sách lưu giữ khác nhau ảnh hưởng đến chú thích của tôi?


175

Bất cứ ai có thể giải thích một cách rõ ràng sự khác biệt thực tiễn giữa các java.lang.annotation.RetentionPolicyhằng số SOURCE, CLASSRUNTIME?

Tôi cũng không chắc chắn chính xác cụm từ "giữ lại chú thích" nghĩa là gì.



vâng tôi đã đọc nhưng tôi không hiểu thực tế nó hoạt động như thế nào. Trong thực tế nếu tôi thử 'cụm từ này': "" "" Các chú thích sẽ được ghi lại trong tệp lớp bởi trình biên dịch nhưng không cần phải được VM giữ lại trong thời gian chạy. "" "và sau đó mở một lớp dịch ngược, trong đó tôi đặt một chú thích với chính sách duy trì LỚP Tôi không tìm thấy gì ...
xdevel2000

2
Sau đó, trình dịch ngược của bạn dường như không hỗ trợ các chú thích. jd-gui hoạt động tốt.
musiKk

Cảm ơn vấn đề là dj dịch ngược của tôi và jad ... jd-gui cho tôi xem !!
xdevel2000

Câu trả lời:


209
  • RetentionPolicy.SOURCE: Hủy trong quá trình biên dịch. Các chú thích này không có ý nghĩa gì sau khi quá trình biên dịch hoàn thành, vì vậy chúng không được ghi vào mã byte.
    Ví dụ: @Override,@SuppressWarnings

  • RetentionPolicy.CLASS: Hủy trong khi tải lớp. Hữu ích khi thực hiện xử lý hậu kỳ cấp mã byte. Thật đáng ngạc nhiên, đây là mặc định.

  • RetentionPolicy.RUNTIME: Đừng bỏ đi. Chú thích nên có sẵn để phản ánh trong thời gian chạy. Thí dụ:@Deprecated

Nguồn: URL cũ đã chết hunter_meta và được thay thế bằng hunter-meta-2-098036 . Trong trường hợp ngay cả điều này đi xuống, tôi đang tải lên hình ảnh của trang.

Hình ảnh (Nhấp chuột phải và chọn 'Mở hình ảnh trong tab / cửa sổ mới') Ảnh chụp màn hình của trang web Oracle


1
cảm ơn vì trích dẫn, điều thú vị nhất ở đây là trường hợp sử dụng choRetentionPolicy.CLASS
Tối đa

1
bạn có thể giải thích tại sao RetentionPolicy. class thú vị / đáng ngạc nhiên là mặc định không?
sudocoder

1
@sudocoder - Tham khảo các liên kết sau: stackoverflow.com/a/5971247/373861stackoverflow.com/a/3849602/373861 . Tôi tin rằng chính sách đặc biệt này là cần thiết cho thiết bị bytecode. Mặc dù tôi không bao giờ sử dụng nó cho mình.
Favonius

Cuối cùng, trong phần tiếp theo của loạt bài này, tôi sẽ chỉ ra cách tăng cường khả năng phản chiếu của Java để giúp bạn khám phá các chú thích trong thời gian chạy và cách "apt" của Công cụ xử lý chú thích cho phép bạn sử dụng các chú thích trong thời gian xây dựng. , bài viết này ở đâu?
Sushant

@Sushant: Chà tôi không chắc nó ở đâu :). Mặc dù aptkhông được dùng nữa, hãy tham khảo tài liệu này.oracle.com / javase / 7 / docs / technotes / guide /apt / . Để khám phá chú thích bằng cách sử dụng sự phản chiếu, có nhiều hướng dẫn trên internet. Bạn có thể bắt đầu bằng cách xem xét java.lang.Class::getAnno*và các phương pháp tương tự trong java.lang.reflect.Methodjava.lang.reflect.Field.
Favonius

57

Theo ý kiến ​​của bạn về dịch ngược lớp, đây là cách tôi nghĩ nó nên hoạt động:

  • RetentionPolicy.SOURCE: Sẽ không xuất hiện trong lớp dịch ngược

  • RetentionPolicy.CLASS: Xuất hiện trong lớp dịch ngược, nhưng không thể được kiểm tra tại thời điểm chạy với sự phản chiếu với getAnnotations()

  • RetentionPolicy.RUNTIME: Xuất hiện trong lớp dịch ngược và có thể được kiểm tra tại thời điểm chạy với sự phản chiếu với getAnnotations()


Vâng tôi cũng nghĩ vậy nhưng trong lớp dịch ngược không có gì cả !!! và do đó tôi bối rối ... Tôi sẽ thử kiểm tra tệp lớp bằng công cụ javap
xdevel2000

javap trả về không có gì được đặt sau đó?
xdevel2000

1
bất kỳ trường hợp sử dụng nào của RetentionPolicy.CLASS?
Raul

20

Ví dụ runnable tối thiểu

Trình độ ngôn ngữ :

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

@Retention(RetentionPolicy.SOURCE)
@interface RetentionSource {}

@Retention(RetentionPolicy.CLASS)
@interface RetentionClass {}

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

public static void main(String[] args) {
    @RetentionSource
    class B {}
    assert B.class.getAnnotations().length == 0;

    @RetentionClass
    class C {}
    assert C.class.getAnnotations().length == 0;

    @RetentionRuntime
    class D {}
    assert D.class.getAnnotations().length == 1;
}

Mức mã byte : sử dụng javapchúng tôi quan sát rằng Retention.CLASSlớp chú thích có thuộc tính lớp RuntimeInvisible :

#14 = Utf8               LRetentionClass;
[...]
RuntimeInvisibleAnnotations:
  0: #14()

trong khi Retention.RUNTIMEchú thích có một thuộc tính lớp RuntimeVisible :

#14 = Utf8               LRetentionRuntime;
[...]
RuntimeVisibleAnnotations:
  0: #14()

Runtime.SOURCEchú thích .classkhông nhận được bất kỳ chú thích nào.

Ví dụ về GitHub để bạn chơi.


Vì vậy, bất kỳ ý tưởng những gì sử dụng Runtime.SOURCE và Runtime.CLASS?
Praveen Kamath

@PraveenKamath Tôi không biết bất kỳ ví dụ nào hữu ích. Chỉ có thể xảy ra nếu bạn đang thực hiện công cụ JVM cấp thấp hơn mà hầu hết các nhà phát triển không bao giờ làm. Hãy cho tôi biết nếu bạn tìm thấy một ứng dụng cho họ.
Ciro Santilli 郝海东 冠状 病 事件

5

Chính sách duy trì: Chính sách duy trì xác định tại thời điểm chú thích bị loại bỏ. Nó được chỉ định bằng cách sử dụng các chú thích dựng sẵn của Java: @Retention[Giới thiệu]

1.SOURCE: annotation retained only in the source file and is discarded
          during compilation.
2.CLASS: annotation stored in the .class file during compilation,
         not available in the run time.
3.RUNTIME: annotation stored in the .class file and available in the run time.

0
  • Trình biên dịch LỚP sẽ được ghi lại trong tệp lớp bởi trình biên dịch nhưng VM không cần phải giữ lại trong thời gian chạy.
  • RUNTIME [ Chú thích sẽ được ghi lại trong tệp lớp bởi trình biên dịch và được VM giữ lại trong thời gian chạy, vì vậy chúng có thể được đọc một cách phản xạ.
  • NGUỒN LỚP Chú thích sẽ bị trình biên dịch loại bỏ.

Tài liệu Oracle

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.