นโยบายการเก็บข้อมูลที่แตกต่างกันมีผลต่อบันทึกย่อของฉันอย่างไร


175

ทุกคนสามารถอธิบายในทางที่ชัดเจนแตกต่างในทางปฏิบัติระหว่างjava.lang.annotation.RetentionPolicyค่าคงที่SOURCE, CLASSและRUNTIME?

ฉันก็ไม่แน่ใจเหมือนกันว่าวลี "การเก็บคำอธิบายประกอบ" หมายถึงอะไร


5
เอกสาร ( java.sun.com/j2se/1.5.0/docs/api/java/lang/annotation/ ...... ) นั้นชัดเจนมาก
True Soft

ใช่ฉันอ่านแล้ว แต่ฉันไม่เข้าใจในทางปฏิบัติมันทำงานอย่างไร ในความเป็นจริงถ้าฉันลอง 'วลีนี้': "" "" คำอธิบายประกอบจะถูกบันทึกไว้ในไฟล์คลาสโดยคอมไพเลอร์ แต่ไม่จำเป็นต้องถูกเก็บรักษาไว้โดย VM ในขณะใช้งาน "" "แล้วเปิดคลาส decompiled ที่ฉันใส่หมายเหตุประกอบกับนโยบายการเก็บข้อมูล CLASS ฉันไม่พบอะไรเลย ...
xdevel2000

2
ดูเหมือนว่า decompiler ของคุณจะไม่รองรับหมายเหตุประกอบ jd-gui ทำงานได้ดี
musiKk

ขอบคุณปัญหาคือ decompiler dj และ jad ของฉัน ... jd-gui แสดงให้ฉันเห็น !!
xdevel2000

คำตอบ:


210
  • RetentionPolicy.SOURCE: ทิ้งระหว่างการคอมไพล์ คำอธิบายประกอบเหล่านี้ไม่สมเหตุสมผลหลังจากคอมไพล์เสร็จสมบูรณ์ดังนั้นจึงไม่ได้เขียนลงใน bytecode
    ตัวอย่าง: @Override,@SuppressWarnings

  • RetentionPolicy.CLASS: ทิ้งระหว่างการโหลดคลาส มีประโยชน์เมื่อทำการประมวลผลภายหลังระดับ bytecode ค่อนข้างน่าประหลาดใจนี่เป็นค่าเริ่มต้น

  • RetentionPolicy.RUNTIME: อย่าทิ้ง คำอธิบายประกอบควรจะมีให้สำหรับการสะท้อนที่รันไทม์ ตัวอย่าง:@Deprecated

ที่มา: URL ที่เก่าที่ตายแล้วในขณะนี้ hunter_metaและแทนที่ด้วยนักล่า meta-2-098036 ในกรณีที่สิ่งนี้เกิดขึ้นฉันกำลังอัปโหลดภาพของหน้า

รูปภาพ (คลิกขวาและเลือก 'เปิดภาพในแท็บ / หน้าต่างใหม่') สกรีนช็อตของเว็บไซต์ Oracle


1
ขอบคุณสำหรับใบเสนอราคาที่น่าสนใจที่สุดคือกรณีใช้งานสำหรับRetentionPolicy.CLASS
Max

2
คุณช่วยอธิบายได้ไหมว่าทำไม RetentionPolicy.class น่าสนใจ / แปลกใจที่เป็นค่าเริ่มต้น
sudocoder

1
@sudocoder - อ้างถึงการเชื่อมโยงเหล่านี้: stackoverflow.com/a/5971247/373861และstackoverflow.com/a/3849602/373861 ฉันเชื่อว่านโยบายนี้เป็นสิ่งจำเป็นสำหรับเครื่องมือวัดของ Bytecode แม้ว่าฉันจะไม่เคยใช้มันเลย
Favonius

ในตอนท้ายมันบอกว่าในบทความถัดไปในชุดนี้ฉันจะแสดงให้เห็นว่าความสามารถในการสะท้อนของ Java ได้รับการปรับปรุงเพื่อช่วยให้คุณค้นพบคำอธิบายประกอบที่รันไทม์และวิธีที่เครื่องมือคำอธิบายประกอบ "apt" ช่วยให้คุณใช้คำอธิบายประกอบได้อย่างไร บทความนี้อยู่ที่ไหน
Sushant

@Sushant: ดีฉันไม่แน่ใจว่ามันอยู่ที่ไหน :) แม้ว่าaptจะเลิกใช้แล้วโปรดอ้างถึงdocs.oracle.com/javase/7/docs/technotes/guides/apt/นี้ สำหรับการค้นหาคำอธิบายประกอบโดยใช้การสะท้อนมีบทเรียนมากมายบนอินเทอร์เน็ต คุณสามารถเริ่มต้นด้วยการมองเข้าไปในjava.lang.Class::getAnno*และวิธีการที่คล้ายกันในและjava.lang.reflect.Method java.lang.reflect.Field
Favonius

57

ตามความคิดเห็นของคุณเกี่ยวกับการแยกย่อยชั้นเรียนนี่คือวิธีที่ฉันคิดว่าควรจะทำงาน

  • RetentionPolicy.SOURCE: จะไม่ปรากฏในคลาสที่ถอดรหัสแล้ว

  • RetentionPolicy.CLASS: ปรากฏในคลาสที่ถอดรหัสแล้ว แต่ไม่สามารถตรวจสอบได้ในเวลาทำงานโดยมีการสะท้อนกลับ getAnnotations()

  • RetentionPolicy.RUNTIME: ปรากฏในคลาสที่ถอดรหัสแล้วและสามารถตรวจสอบได้ในเวลาทำงานโดยมีการสะท้อนกลับด้วย getAnnotations()


ใช่ฉันก็คิดอย่างนั้นเช่นกัน แต่ในชั้นเรียนที่ไม่มีการแบ่งแยกไม่มีอะไร !!! และดังนั้นฉันสับสน ... ฉันจะพยายามตรวจสอบไฟล์คลาสด้วยเครื่องมือ javap
xdevel2000

javap ไม่ส่งคืนสิ่งที่วางไว้แล้ว?
xdevel2000

1
กรณีการใช้งานของ RetentionPolicy.CLASS?
ราหุล

20

ตัวอย่างที่เรียกใช้น้อยที่สุด

ระดับภาษา :

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

ระดับ Bytecode : การใช้javapเราสังเกตว่าRetention.CLASSคลาสที่ทำหมายเหตุประกอบไว้จะได้รับแอตทริบิวต์ของคลาสRuntimeInvisible :

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

ขณะที่Retention.RUNTIMEคำอธิบายประกอบจะได้รับคุณลักษณะคลาสRuntimeVisible :

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

และRuntime.SOURCEคำอธิบายประกอบ.classจะไม่ได้รับการเพิ่มความคิดเห็นใด ๆ

ตัวอย่างบน GitHubเพื่อให้คุณเล่นด้วย


ดังนั้นแนวคิดใดที่ใช้ Runtime.SOURCE และ Runtime.CLASS
Praveen Kamath

@PraveenKamath ฉันไม่รู้จักตัวอย่างใด ๆ ที่มีประโยชน์ อาจเกิดขึ้นได้ก็ต่อเมื่อคุณกำลังทำ JVM ระดับต่ำกว่าที่ devs ส่วนใหญ่ไม่เคยทำ แจ้งให้เราทราบหากคุณพบแอปพลิเคชันสำหรับพวกเขา
Ciro Santilli 郝海东冠状病六四事件法轮功

5

นโยบายการเก็บรักษา: นโยบายการเก็บรักษาจะเป็นตัวกำหนดว่าการยกเลิกหมายเหตุประกอบจะมีจุดใด มันถูกระบุโดยใช้คำอธิบายประกอบในตัวของ Java: @Retention[เกี่ยวกับ]

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
  • คลาส : คำอธิบายประกอบจะถูกบันทึกไว้ในไฟล์คลาสโดยคอมไพเลอร์ แต่ไม่จำเป็นต้องเก็บรักษาไว้โดย VM ในขณะใช้งาน
  • RUNTIME : คำอธิบายประกอบจะถูกบันทึกไว้ในไฟล์คลาสโดยคอมไพเลอร์และเก็บรักษาไว้โดย VM ในขณะใช้งานดังนั้นจึงอาจอ่านได้อย่างชัดเจน
  • แหล่งที่มา : คอมไพเลอร์จะถูกทิ้ง

Oracle Doc

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.