Bagaimana kebijakan retensi yang berbeda memengaruhi anotasi saya?

175

Siapa pun dapat menjelaskan dengan cara yang jelas perbedaan praktis antara java.lang.annotation.RetentionPolicykonstanta SOURCE, CLASSdan RUNTIME?

Saya juga tidak yakin apa arti frasa "mempertahankan anotasi".

xdevel2000
sumber
5
Dokumentasi ( java.sun.com/j2se/1.5.0/docs/api/java/lang/annotation/… ) sangat jelas.
True Soft
ya saya sudah membaca tetapi saya tidak mengerti bagaimana cara kerjanya. Sebenarnya jika saya mencoba 'frasa ini': "" "" Anotasi harus direkam dalam file kelas oleh kompiler tetapi tidak perlu disimpan oleh VM pada saat dijalankan. "" "dan kemudian buka kelas yang didekompilasi di mana saya meletakkan anotasi dengan kebijakan penyimpanan CLASS Saya tidak menemukan apa-apa ...
xdevel2000
2
Maka dekompiler Anda tampaknya tidak mendukung anotasi. jd-gui berfungsi dengan baik.
musiKk
Terima kasih masalahnya adalah dekompiler dj dan jad saya ... jd-gui tunjukkan padaku !!
xdevel2000

Jawaban:

210
  • RetentionPolicy.SOURCE: Buang selama kompilasi. Anotasi ini tidak masuk akal setelah kompilasi selesai, sehingga tidak ditulis ke bytecode.
    Contoh: @Override,@SuppressWarnings

  • RetentionPolicy.CLASS: Buang selama pemuatan kelas. Berguna saat melakukan bytecode-level post-processing. Agak mengherankan, ini adalah default.

  • RetentionPolicy.RUNTIME: Jangan dibuang. Anotasi harus tersedia untuk refleksi saat runtime. Contoh:@Deprecated

Sumber: URL lama sudah mati sekarang hunter_meta dan diganti dengan hunter-meta-2-098036 . Seandainya ini turun, saya mengunggah gambar halaman.

Gambar (Klik Kanan dan Pilih 'Buka Gambar di Tab / Jendela Baru') Cuplikan layar situs web Oracle

Favonius
sumber
1
terima kasih untuk penawarannya, yang paling menarik di sini adalah kasus penggunaan untukRetentionPolicy.CLASS
Max
2
dapatkah Anda menjelaskan mengapa RetentionPolicy.class menarik / secara mengejutkan merupakan default?
sudocoder
1
@sudocoder - Lihat tautan ini: stackoverflow.com/a/5971247/373861 dan stackoverflow.com/a/3849602/373861 . Saya percaya kebijakan khusus ini diperlukan untuk instrumentasi bytecode. Padahal saya tidak pernah menggunakannya sendiri.
Favonius
Pada akhirnya dikatakan Dalam artikel selanjutnya dalam seri ini, saya akan menunjukkan bagaimana kemampuan refleksi Java telah ditingkatkan untuk membantu Anda menemukan anotasi saat runtime dan bagaimana Alat Pemrosesan Anotasi "apt" memungkinkan Anda menggunakan anotasi saat membangun. , dimana artikel ini?
Sushant
@ Sushant: Ya saya tidak yakin di mana itu :). Meskipun aptsudah usang, lihat dokumen inis.oracle.com/javase/7/docs/technotes/guides/apt/… . Untuk menemukan anotasi menggunakan refleksi ada beberapa tutorial di internet. Anda dapat mulai dengan melihat java.lang.Class::getAnno*dan metode serupa di dalam java.lang.reflect.Methoddan java.lang.reflect.Field.
Favonius
57

Menurut komentar Anda tentang dekompilasi kelas, berikut ini menurut saya cara kerjanya:

  • RetentionPolicy.SOURCE: Tidak akan muncul di kelas yang didekompilasi

  • RetentionPolicy.CLASS: Tampil di kelas yang didekompilasi, tetapi tidak dapat diperiksa pada saat run-time dengan refleksi dengan getAnnotations()

  • RetentionPolicy.RUNTIME: Tampil di kelas yang didekompilasi, dan dapat diperiksa pada saat dijalankan dengan refleksi bersama getAnnotations()

ewernli
sumber
Ya, saya juga berpikir begitu, tetapi di kelas yang didekompilasi tidak ada yang hadir !!! dan karena itu saya bingung ... Saya akan mencoba memeriksa file kelas dengan alat javap
xdevel2000
javap mengembalikan apa-apa di mana kemudian?
xdevel2000
1
ada kasus penggunaan RetentionPolicy.CLASS?
Rahul
20

Contoh runnable minimal

Tingkat bahasa :

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

Level bytecode : menggunakan javapkami amati bahwa Retention.CLASSkelas yang diberi catatan mendapat atribut kelas RuntimeInvisible :

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

sementara Retention.RUNTIMEanotasi mendapat atribut kelas RuntimeVisible :

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

dan Runtime.SOURCEanotasi .classtidak mendapatkan anotasi.

Contoh di GitHub untuk Anda mainkan.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
Jadi ada ide apa gunanya Runtime. SUMBER dan Runtime.CLASS?
Praveen Kamath
@PraveenKamath Saya tidak tahu contoh mana yang berguna. Kemungkinan hanya terjadi jika Anda melakukan hal-hal JVM tingkat yang lebih rendah yang sebagian besar pengembang tidak pernah melakukannya. Beri tahu saya jika Anda menemukan aplikasi untuk mereka.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
5

Kebijakan Retensi: Kebijakan retensi menentukan pada titik mana anotasi dibuang. Ini ditentukan menggunakan anotasi bawaan Java: @Retention[Tentang]

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.
Ferdous Wahid
sumber
0
  • CLASS : Anotasi harus direkam dalam file kelas oleh kompiler tetapi tidak perlu disimpan oleh VM pada saat run time.
  • RUNTIME : Anotasi direkam dalam file kelas oleh kompiler dan disimpan oleh VM pada saat run time, sehingga mereka dapat dibaca secara reflektif.
  • SUMBER : Anotasi harus dibuang oleh kompiler.

Oracle Doc

Michael Wong
sumber