การสะท้อนกลับคืออะไรและทำไมจึงมีประโยชน์


2124

การสะท้อนกลับคืออะไรและทำไมจึงมีประโยชน์

ฉันสนใจ Java เป็นพิเศษ แต่ฉันคิดว่าหลักการเหมือนกันในทุกภาษา


9
สำหรับฉันมันเป็นวิธีการรับชื่อคลาสที่รันไทม์และสร้างวัตถุของคลาสนั้น
Nabin

64
เพราะนี่เป็นคำถามยอดนิยมที่ฉันต้องการชี้ให้เห็นว่าการสะท้อน (โดยไม่มีคำอธิบายประกอบ) ควรเป็นเครื่องมือสุดท้ายที่คุณจะได้รับเมื่อแก้ไขปัญหา ฉันใช้และรักมัน แต่ก็ยกเลิกข้อได้เปรียบทั้งหมดของการพิมพ์แบบคงที่ของ Java หากคุณต้องการให้แยกพื้นที่ขนาดเล็กที่สุดเท่าที่จะเป็นไปได้ (หนึ่งวิธีหรือหนึ่งคลาส) เป็นที่ยอมรับได้มากกว่าที่จะใช้ในการทดสอบมากกว่ารหัสการผลิต ด้วยคำอธิบายประกอบมันควรจะดี - ประเด็นหลักคือไม่ต้องระบุชื่อคลาสหรือเมธอดเป็น "Strings" หากคุณสามารถหลีกเลี่ยงได้
Bill K

2
ดูเพิ่มเติมที่: softwareengineering.stackexchange.com/questions/123956/…
givanse

4
นอกจากความเห็นของ @ BillK: Reflection นั้นทรงพลังมากฉันจะเรียกมันว่าเวทมนต์ ด้วยพลังอันยิ่งใหญ่มาพร้อมความรับผิดชอบที่ดี ใช้มันเฉพาะเมื่อคุณรู้ว่าคุณกำลังทำอะไรอยู่
MC Emperor

คุณสามารถหลีกเลี่ยงข้อผิดพลาดหลายที่เกี่ยวข้องกับการสะท้อนให้เห็นถึงการใช้ @JailbreakManifold มันให้การเข้าถึงโดยตรงประเภทปลอดภัยไปยังเขตข้อมูลส่วนตัววิธีการ ฯลฯ ให้คอมไพเลอร์ Java ตรวจสอบรหัสของคุณอย่างปลอดภัยและให้ Manifold สร้างการเข้าถึงการสะท้อนพื้นฐานสำหรับคุณ เรียนรู้เพิ่มเติม: manifold.systems/docs.html#type-safe-reflection
Scott

คำตอบ:


1716

การสะท้อนชื่อใช้เพื่ออธิบายรหัสที่สามารถตรวจสอบรหัสอื่นในระบบเดียวกัน (หรือตัวเอง)

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

ดังนั้นเพื่อให้ตัวอย่างรหัสนี้ใน Java (จินตนาการวัตถุในคำถามคือ foo):

Method method = foo.getClass().getMethod("doSomething", null);
method.invoke(foo, null);

กรณีการใช้งานทั่วไปอย่างหนึ่งใน Java คือการใช้พร้อมหมายเหตุประกอบ ตัวอย่างเช่น JUnit 4 จะใช้การสะท้อนเพื่อดูคลาสของคุณสำหรับเมธอดที่ติดแท็กด้วยคำอธิบายประกอบ @Test และจะเรียกใช้เมื่อทำการทดสอบหน่วย

มีตัวอย่างการสะท้อนที่ดีเพื่อให้คุณเริ่มต้นได้ที่http://docs.oracle.com/javase/tutorial/reflect/index.html

และสุดท้ายก็ใช่แล้วแนวคิดเหล่านี้คล้ายกันมากในภาษาที่พิมพ์แบบคงที่อื่น ๆ ซึ่งสนับสนุนการสะท้อน (เช่น C #) ในภาษาที่พิมพ์แบบไดนามิกกรณีการใช้ที่อธิบายไว้ข้างต้นมีความจำเป็นน้อยกว่า (เนื่องจากคอมไพเลอร์จะอนุญาตให้วิธีการใด ๆ ที่จะเรียกใช้บนวัตถุใด ๆ ความล้มเหลวที่รันไทม์หากไม่มีอยู่) แต่กรณีที่สองของการค้นหาวิธีการ การทำงานในลักษณะที่แน่นอนยังคงเป็นเรื่องปกติ

อัปเดตจากความคิดเห็น:

ความสามารถในการตรวจสอบรหัสในระบบและดูประเภทวัตถุไม่ได้สะท้อน แต่เป็นการพิมพ์วิปัสสนา การสะท้อนนั้นเป็นความสามารถในการปรับเปลี่ยนที่รันไทม์โดยใช้การวิปัสสนา ความแตกต่างเป็นสิ่งจำเป็นที่นี่เนื่องจากบางภาษารองรับการใคร่ครวญ แต่ไม่สนับสนุนการสะท้อนกลับ ตัวอย่างหนึ่งคือ C ++


32
คุณช่วยอธิบายได้ว่าอะไรคือความสำคัญของพารามิเตอร์ null ในเมธอด line method นี้ = foo.getClass (). getMethod ("doSomething", null);
Krsna Chaitanya

54
null ระบุว่าไม่มีพารามิเตอร์ที่ถูกส่งผ่านไปยังวิธี foo ดูdocs.oracle.com/javase/6/docs/api/java/lang/reflect/… , java.lang.Object ... ) สำหรับรายละเอียด
Matt Sheppard

791
แค่เคลียร์เพราะมันมี upvotes มากมาย ความสามารถในการตรวจสอบรหัสในระบบและดูประเภทวัตถุนั้นไม่ได้สะท้อน แต่เป็นการพิมพ์แบบวิปัสสนา การสะท้อนนั้นเป็นความสามารถในการปรับเปลี่ยนที่รันไทม์โดยใช้การวิปัสสนา ความแตกต่างเป็นสิ่งที่จำเป็นเนื่องจากบางภาษารองรับการใคร่ครวญ แต่ไม่สนับสนุนการสะท้อนกลับ ตัวอย่างหนึ่งคือ C ++
bigtunacan

39
ฉันรักการไตร่ตรอง แต่ถ้าคุณสามารถควบคุมรหัสได้ดังนั้นการใช้การสะท้อนกลับตามที่ระบุไว้ในคำตอบนี้จึงเป็นสิ่งที่ไม่ดีและดังนั้นจึงเป็นการละเมิด - คุณควรใช้การวิปัสสนาประเภท (instanceof) และประเภทที่รัดกุม หากมีวิธีใดนอกจากสะท้อนที่จะทำบางสิ่งนั่นคือสิ่งที่ควรทำ การไตร่ตรองทำให้เกิดอาการปวดใจอย่างรุนแรงเนื่องจากคุณสูญเสียความได้เปรียบทั้งหมดในการใช้ภาษาที่พิมพ์แบบคงที่ หากคุณต้องการคุณจำเป็นต้องใช้มันอย่างไรก็ตามถึงกระนั้นฉันก็จะพิจารณาวิธีแก้ปัญหาที่เตรียมไว้ล่วงหน้าเช่น Spring หรือบางสิ่งที่สะท้อนการสะท้อนที่จำเป็นอย่างสมบูรณ์ - IE: ปล่อยให้คนอื่นมีอาการปวดหัว
Bill K

6
@bigtunacan คุณได้รับข้อมูลจากที่ใด ฉันเห็นคำว่า "การสะท้อน" ที่ใช้ในเอกสารคู่มือ Java อย่างเป็นทางการจาก Oracle เพื่ออธิบายไม่เพียง แต่ความสามารถในการเปลี่ยนแปลงที่รันไทม์ แต่ยังสามารถดูประเภทของวัตถุได้ ไม่ต้องพูดถึงว่าส่วนใหญ่ที่เรียกว่า "ประเภทวิปัสสนา" เรียนที่เกี่ยวข้อง (เช่น: Method, Constructor, Modifier, Field, Memberโดยทั่วไปเห็นได้ชัดว่าทั้งหมดยกเว้นClass) อยู่ในjava.lang.*reflect*แพคเกจ บางทีแนวคิด "การสะท้อน" อาจครอบคลุมทั้ง "วิปัสสนาชนิด" และการปรับเปลี่ยนในเวลาทำงาน?
RestInPeace

246

Reflectionเป็นความสามารถของภาษาในการตรวจสอบและเรียกคลาส, เมธอด, คุณลักษณะ, ฯลฯ ที่รันไทม์

ตัวอย่างเช่นวัตถุทั้งหมดใน Java มีวิธีการgetClass()ที่ช่วยให้คุณกำหนดระดับของวัตถุแม้ว่าคุณจะไม่ทราบว่าในเวลารวบรวม (เช่นถ้าคุณประกาศว่าเป็นObject) - นี้อาจดูเหมือนเล็กน้อย แต่การสะท้อนดังกล่าวเป็นไปไม่ได้ C++ในเวลาที่น้อยภาษาแบบไดนามิกเช่น การใช้งานขั้นสูงเพิ่มเติมช่วยให้คุณแสดงรายการและวิธีการโทรคอนสตรัคเตอร์ ฯลฯ

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

กรอบงานสมัยใหม่จำนวนมากใช้การสะท้อนอย่างกว้างขวางด้วยเหตุผลนี้ ภาษาสมัยใหม่อื่น ๆ ส่วนใหญ่ใช้การสะท้อนเช่นกันและในภาษาสคริปต์ (เช่น Python) พวกเขาจะถูกรวมเข้าด้วยกันแน่นยิ่งขึ้นเนื่องจากมันให้ความรู้สึกเป็นธรรมชาติมากกว่าในรูปแบบการเขียนโปรแกรมทั่วไปของภาษาเหล่านั้น


2
ดังนั้นในคำอื่น ๆ คุณสามารถสร้างอินสแตนซ์จากชื่อที่ผ่านการรับรองและคอมไพเลอร์จะไม่บ่นเกี่ยวกับมัน (เพราะบอกว่าคุณใช้เพียงสตริงสำหรับชื่อคลาส) จากนั้น ณ รันไทม์หากคลาสนั้นไม่ปรากฏขึ้นคุณจะได้รับข้อยกเว้น คุณข้ามคอมไพเลอร์ในกรณีนี้ คุณจะให้กรณีการใช้งานบางอย่างให้ฉันได้ไหม ฉันไม่สามารถถ่ายรูปได้เมื่อฉันจะเลือก
เฟอร์นันโดกาเบรีลี

3
@FernandoGabrieli ในขณะที่มันเป็นความจริงที่มันง่ายที่จะสร้างข้อผิดพลาดรันไทม์ที่มีการสะท้อนก็ยังเป็นไปได้อย่างสมบูรณ์แบบที่จะใช้การสะท้อนโดยไม่ต้องเสี่ยงกับข้อยกเว้นรันไทม์ ตามที่ระบุไว้ในคำตอบของฉันการใช้งานทั่วไปของการสะท้อนนั้นมีไว้สำหรับไลบรารีหรือกรอบซึ่งไม่สามารถทราบโครงสร้างของแอปพลิเคชันในเวลารวบรวมได้อย่างชัดเจนเนื่องจากถูกรวบรวมแยกจากแอปพลิเคชัน ไลบรารีใด ๆ ที่ใช้ "code by conference" มีแนวโน้มที่จะใช้การสะท้อนกลับ แต่ไม่จำเป็นต้องใช้สตริงมายากล
Liedman

C++ไม่มีข้อมูลชนิดรันไทม์ RTTI
Ayxan

114

หนึ่งในการใช้การสะท้อนที่ฉันโปรดปรานคือวิธีการถ่ายโอนข้อมูล Java ด้านล่าง ใช้วัตถุใด ๆ เป็นพารามิเตอร์และใช้ Java reflection API เพื่อพิมพ์ชื่อและค่าของฟิลด์ทั้งหมด

import java.lang.reflect.Array;
import java.lang.reflect.Field;

public static String dump(Object o, int callCount) {
    callCount++;
    StringBuffer tabs = new StringBuffer();
    for (int k = 0; k < callCount; k++) {
        tabs.append("\t");
    }
    StringBuffer buffer = new StringBuffer();
    Class oClass = o.getClass();
    if (oClass.isArray()) {
        buffer.append("\n");
        buffer.append(tabs.toString());
        buffer.append("[");
        for (int i = 0; i < Array.getLength(o); i++) {
            if (i < 0)
                buffer.append(",");
            Object value = Array.get(o, i);
            if (value.getClass().isPrimitive() ||
                    value.getClass() == java.lang.Long.class ||
                    value.getClass() == java.lang.String.class ||
                    value.getClass() == java.lang.Integer.class ||
                    value.getClass() == java.lang.Boolean.class
                    ) {
                buffer.append(value);
            } else {
                buffer.append(dump(value, callCount));
            }
        }
        buffer.append(tabs.toString());
        buffer.append("]\n");
    } else {
        buffer.append("\n");
        buffer.append(tabs.toString());
        buffer.append("{\n");
        while (oClass != null) {
            Field[] fields = oClass.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                buffer.append(tabs.toString());
                fields[i].setAccessible(true);
                buffer.append(fields[i].getName());
                buffer.append("=");
                try {
                    Object value = fields[i].get(o);
                    if (value != null) {
                        if (value.getClass().isPrimitive() ||
                                value.getClass() == java.lang.Long.class ||
                                value.getClass() == java.lang.String.class ||
                                value.getClass() == java.lang.Integer.class ||
                                value.getClass() == java.lang.Boolean.class
                                ) {
                            buffer.append(value);
                        } else {
                            buffer.append(dump(value, callCount));
                        }
                    }
                } catch (IllegalAccessException e) {
                    buffer.append(e.getMessage());
                }
                buffer.append("\n");
            }
            oClass = oClass.getSuperclass();
        }
        buffer.append(tabs.toString());
        buffer.append("}\n");
    }
    return buffer.toString();
}

8
Callcount ควรตั้งค่าเป็นอะไร?
ทอม

8
ฉันได้รับข้อยกเว้นในเธรด "AWT-EventQueue-0" java.lang.StackOverflowError เมื่อฉันรันสิ่งนี้
ทอม

3
@ Tom callCountควรตั้งค่าเป็นศูนย์ ค่าของมันถูกใช้เพื่อกำหนดจำนวนแท็บที่ควรนำหน้าแต่ละบรรทัดของเอาต์พุต: แต่ละครั้งที่ดัมพ์ต้องการดัมพ์ "subobject" เอาต์พุตจะพิมพ์เป็นซ้อนกันในพาเรนต์ วิธีการนั้นพิสูจน์ได้ว่ามีประโยชน์เมื่อห่อหุ้มด้วยวิธีอื่น printDump(Object obj){ System.out.println(dump(obj, 0)); }พิจารณา
fny

1
java.lang.StackOverflowError อาจถูกสร้างขึ้นในกรณีของการอ้างอิงแบบวงกลมเนื่องจากการเรียกซ้ำแบบไม่ จำกัด : buffer.append (dump (value, callCount))
Arnaud P

4
คุณสามารถปล่อยรหัสของคุณเป็นโดเมนสาธารณะได้ไหมได้ไหม
stolsvik

84

การใช้การสะท้อน

การสะท้อนมักใช้โดยโปรแกรมที่ต้องการความสามารถในการตรวจสอบหรือแก้ไขพฤติกรรมการใช้งานจริงของแอพพลิเคชั่นที่รันในเครื่องเสมือน Java นี่เป็นคุณลักษณะขั้นสูงและควรใช้โดยนักพัฒนาที่เข้าใจพื้นฐานของภาษาอย่างมาก ด้วยข้อแม้นั้นการไตร่ตรองจึงเป็นเทคนิคที่ทรงพลังและสามารถเปิดใช้งานแอปพลิเคชั่นเพื่อการดำเนินการ

คุณสมบัติเสริม

แอปพลิเคชันอาจใช้คลาสภายนอกที่ผู้ใช้กำหนดโดยการสร้างอินสแตนซ์ของวัตถุที่ขยายได้โดยใช้ชื่อที่ผ่านการรับรอง เบราว์เซอร์ของชั้นเรียนและสภาพแวดล้อมการพัฒนาด้านภาพเบราว์เซอร์ของชั้นเรียนจะต้องสามารถระบุสมาชิกของคลาสได้ สภาพแวดล้อมการพัฒนาด้านภาพสามารถได้รับประโยชน์จากการใช้ข้อมูลประเภทที่มีอยู่ในภาพสะท้อนเพื่อช่วยผู้พัฒนาในการเขียนรหัสที่ถูกต้อง เครื่องมือดีบั๊กและเครื่องมือทดสอบ Debuggers จำเป็นต้องสามารถตรวจสอบสมาชิกส่วนตัวในชั้นเรียน ชุดทดสอบสามารถใช้การสะท้อนเพื่อเรียกชุด API ที่ค้นพบได้ซึ่งกำหนดไว้ในคลาสอย่างเป็นระบบเพื่อให้แน่ใจว่าครอบคลุมรหัสระดับสูงในชุดทดสอบ

ข้อเสียของการสะท้อน

การสะท้อนกลับมีพลัง แต่ไม่ควรใช้โดยไม่เลือกหน้า หากเป็นไปได้ที่จะทำการดำเนินการโดยไม่ใช้การสะท้อนกลับจะเป็นการดีกว่าที่จะหลีกเลี่ยงการใช้งาน ข้อควรระวังต่อไปนี้ควรคำนึงถึงเมื่อเข้าถึงรหัสผ่านการสะท้อนกลับ

  • ประสิทธิภาพค่าใช้จ่าย

เนื่องจากการสะท้อนกลับเกี่ยวข้องกับชนิดที่แก้ไขแบบไดนามิกไม่สามารถทำการปรับให้เหมาะสมของเครื่องเสมือน Java ได้ ดังนั้นการดำเนินการไตร่ตรองจึงมีประสิทธิภาพการทำงานที่ช้ากว่าคู่ที่ไม่ได้ไตร่ตรองและควรหลีกเลี่ยงในส่วนของโค้ดซึ่งถูกเรียกใช้บ่อยครั้งในแอปพลิเคชันที่ไวต่อประสิทธิภาพ

  • ข้อ จำกัด ด้านความปลอดภัย

Reflection ต้องการการอนุญาตแบบ runtime ซึ่งอาจไม่ปรากฏเมื่อทำงานภายใต้ตัวจัดการความปลอดภัย นี่คือการพิจารณาที่สำคัญสำหรับรหัสที่จะต้องทำงานในบริบทความปลอดภัยที่ จำกัด เช่นในแอปเพล็ต

  • การได้รับสารจากภายใน

เนื่องจากการสะท้อนกลับทำให้โค้ดสามารถดำเนินการที่ผิดกฎหมายในโค้ดที่ไม่สะท้อนแสงเช่นการเข้าถึงฟิลด์และวิธีการส่วนตัวการใช้การสะท้อนอาจส่งผลให้เกิดผลข้างเคียงที่ไม่คาดคิดซึ่งอาจทำให้โค้ดไม่สมบูรณ์และอาจทำลายความพกพาได้ รหัสไตร่ตรองจะแยกบทคัดย่อและอาจเปลี่ยนพฤติกรรมด้วยการอัปเกรดแพลตฟอร์ม

แหล่งที่มา: Reflection API


44

Reflection เป็นกลไกสำคัญในการอนุญาตให้แอปพลิเคชันหรือเฟรมเวิร์กทำงานกับโค้ดที่อาจยังไม่ได้เขียน!

ยกตัวอย่างไฟล์ web.xml ทั่วไปของคุณ สิ่งนี้จะมีรายการองค์ประกอบของเซิร์ฟเล็ตซึ่งมีองค์ประกอบของคลาสเซิร์ฟเล็ตที่ซ้อนกัน เซิร์ฟเล็ตคอนเทนเนอร์จะประมวลผลไฟล์ web.xml และสร้างอินสแตนซ์ใหม่ของแต่ละคลาสเซิร์ฟเล็ตผ่านการสะท้อนกลับ

อีกตัวอย่างหนึ่งก็จะเป็นใน Java API สำหรับการแยกวิเคราะห์ XML (JAXP) ตำแหน่งที่ผู้ให้บริการวิเคราะห์คำ XML ถูก 'เสียบปลั๊ก' ผ่านคุณสมบัติระบบที่รู้จักกันดีซึ่งใช้ในการสร้างอินสแตนซ์ใหม่ผ่านการสะท้อนกลับ

และในที่สุดตัวอย่างที่ครอบคลุมมากที่สุดคือฤดูใบไม้ผลิซึ่งใช้การสะท้อนเพื่อสร้างถั่วและสำหรับการใช้งานอย่างหนักของผู้รับมอบฉันทะ


36

ไม่ใช่ทุกภาษาที่สนับสนุนการสะท้อน แต่หลักการมักจะเหมือนกันในภาษาที่รองรับ

Reflection คือความสามารถในการ "สะท้อน" กับโครงสร้างของโปรแกรมของคุณ หรือเป็นรูปธรรมมากขึ้น เมื่อต้องการดูวัตถุและคลาสที่คุณมีและรับข้อมูลทางเมธอดฟิลด์และอินเทอร์เฟซที่ใช้งาน คุณยังสามารถดูสิ่งต่าง ๆ เช่นคำอธิบายประกอบ

มันมีประโยชน์ในหลาย ๆ สถานการณ์ ทุกที่ที่คุณต้องการสามารถเสียบคลาสเข้ากับโค้ดของคุณได้ ผู้ทำแผนที่เชิงสัมพันธ์จำนวนมากใช้การสะท้อนเพื่อให้สามารถยกตัวอย่างวัตถุจากฐานข้อมูลโดยไม่ทราบล่วงหน้าว่าจะใช้วัตถุใด สถาปัตยกรรมปลั๊กอินเป็นอีกสถานที่ที่การสะท้อนแสงเป็นประโยชน์ ความสามารถในการโหลดรหัสแบบไดนามิกและตรวจสอบว่ามีประเภทที่ใช้อินเตอร์เฟซที่เหมาะสมที่จะใช้เป็นปลั๊กอินมีความสำคัญในสถานการณ์เหล่านั้น


ฉันต้องการยกตัวอย่างวัตถุตามข้อมูลที่มีอยู่ในฐานข้อมูล ฉันเชื่อว่านี่คือสิ่งที่คุณกำลังพูดถึง โค้ดตัวอย่างจะช่วยฉันได้มาก ขอบคุณล่วงหน้า.
อะตอม

34

การสะท้อนกลับช่วยให้การสร้างอินสแตนซ์ของวัตถุใหม่การเรียกใช้เมธอดและการดำเนินการ / ตั้งค่าตัวแปรคลาสแบบไดนามิก ณ รันไทม์โดยไม่ต้องมีความรู้มาก่อนในการนำไปใช้

Class myObjectClass = MyObject.class;
Method[] method = myObjectClass.getMethods();

//Here the method takes a string parameter if there is no param, put null.
Method method = aClass.getMethod("method_name", String.class); 

Object returnValue = method.invoke(null, "parameter-value1");

ในตัวอย่างด้านบนพารามิเตอร์ null เป็นวัตถุที่คุณต้องการเรียกใช้เมธอด หากวิธีการเป็นแบบคงที่คุณให้เป็นโมฆะ หากวิธีการนี้ไม่คงที่ในขณะที่เรียกใช้คุณจะต้องระบุอินสแตนซ์ MyObject ที่ถูกต้องแทนค่า Null

รีเฟลคชั่นยังช่วยให้คุณเข้าถึงสมาชิกส่วนตัว / วิธีการของชั้นเรียน:

public class A{

  private String str= null;

  public A(String str) {
  this.str= str;
  }
}

.

A obj= new A("Some value");

Field privateStringField = A.class.getDeclaredField("privateString");

//Turn off access check for this field
privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(obj);
System.out.println("fieldValue = " + fieldValue);
  • สำหรับการตรวจสอบคลาส (หรือรู้ว่าเป็นการวิปัสสนา) คุณไม่จำเป็นต้องนำเข้าแพคเกจการสะท้อนกลับ ( java.lang.reflect) java.lang.Classเมตาดาต้าระดับสามารถเข้าถึงได้ผ่าน

Reflection เป็น API ที่ทรงพลังมาก แต่อาจทำให้แอปพลิเคชั่นช้าลงหากใช้งานเกินจำนวน


21

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

ตัวอย่าง Java Reflection อย่างรวดเร็วเพื่อแสดงให้คุณเห็นว่าการใช้การสะท้อนนั้นเป็นอย่างไร:

Method[] methods = MyObject.class.getMethods();

    for(Method method : methods){
        System.out.println("method = " + method.getName());
    }

ตัวอย่างนี้รับวัตถุคลาจากคลาสที่เรียกว่า MyObject เมื่อใช้คลาสอ็อบเจ็กต์ตัวอย่างจะได้รับรายการเมธอดในคลาสนั้นวนซ้ำเมธอดและพิมพ์ชื่อของคลาสนั้น

วิธีการทำงานทั้งหมดนี้ถูกอธิบายที่นี่อย่างแน่นอน

แก้ไข : หลังจากเกือบ 1 ปีฉันกำลังแก้ไขคำตอบนี้ในขณะที่อ่านเกี่ยวกับการสะท้อนฉันได้ใช้ Reflection อีกสองสามครั้ง

  • Spring ใช้การกำหนดค่าถั่วเช่น:


<bean id="someID" class="com.example.Foo">
    <property name="someField" value="someValue" />
</bean>

เมื่อบริบท Spring ประมวลผลองค์ประกอบ <bean> นี้จะใช้ Class.forName (String) กับอาร์กิวเมนต์ "com.example.Foo" เพื่อสร้างอินสแตนซ์ของ Class นั้น

จากนั้นจะใช้การสะท้อนอีกครั้งเพื่อรับตัวตั้งค่าที่เหมาะสมสำหรับองค์ประกอบ <คุณสมบัติ> และตั้งค่าเป็นค่าที่ระบุ

  • Junit ใช้ Reflection โดยเฉพาะสำหรับการทดสอบวิธีการส่วนตัว / ที่ได้รับการป้องกัน

สำหรับวิธีการส่วนตัว

Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

สำหรับเขตข้อมูลส่วนตัว

Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

21

ตัวอย่าง:

ยกตัวอย่างแอปพลิเคชันระยะไกลที่ให้แอปพลิเคชันของคุณเป็นวัตถุที่คุณได้รับโดยใช้วิธีการ API ตอนนี้ขึ้นอยู่กับวัตถุที่คุณอาจต้องทำการคำนวณบางอย่าง

ผู้ให้บริการรับประกันว่าวัตถุสามารถมี 3 ประเภทและเราจำเป็นต้องทำการคำนวณตามประเภทของวัตถุ

ดังนั้นเราอาจใช้ 3 คลาสในแต่ละคลาสที่มีลอจิกที่แตกต่างกันอย่างชัดเจนดังนั้นข้อมูลวัตถุจึงมีอยู่ในรันไทม์ดังนั้นคุณจึงไม่สามารถใช้รหัสในการคำนวณแบบสแตติกได้ วัตถุที่ได้รับจากผู้ให้บริการ


ฉันต้องการบางสิ่งที่คล้ายกัน .. ตัวอย่างจะช่วยฉันได้มากในขณะที่ฉันยังใหม่กับแนวคิดการไตร่ตรอง ..
Atom

2
ฉันสับสน: คุณไม่สามารถใช้instanceofเพื่อกำหนดประเภทของวัตถุเมื่อรันไทม์?
ndm13

19

ตัวอย่างง่าย ๆ สำหรับการสะท้อนกลับ ในเกมหมากรุกคุณไม่ทราบว่าผู้ใช้จะถูกย้ายในเวลาทำงาน การสะท้อนกลับสามารถใช้ในการเรียกใช้เมธอดที่มีการใช้งานแล้วในขณะใช้งาน:

public class Test {

    public void firstMoveChoice(){
        System.out.println("First Move");
    } 
    public void secondMOveChoice(){
        System.out.println("Second Move");
    }
    public void thirdMoveChoice(){
        System.out.println("Third Move");
    }

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 
        Test test = new Test();
        Method[] method = test.getClass().getMethods();
        //firstMoveChoice
        method[0].invoke(test, null);
        //secondMoveChoice
        method[1].invoke(test, null);
        //thirdMoveChoice
        method[2].invoke(test, null);
    }

}

18

Reflectionเป็น API ที่ใช้ในการตรวจสอบหรือแก้ไขพฤติกรรมของวิธีการเรียนอินเตอร์เฟซที่รันไทม์

  1. java.lang.reflect packageเรียนที่จำเป็นสำหรับการสะท้อนอยู่ภายใต้
  2. Reflection ให้ข้อมูลเกี่ยวกับคลาสที่วัตถุเป็นของเราและวิธีการของคลาสนั้นซึ่งสามารถดำเนินการได้โดยใช้วัตถุ
  3. ด้วยการไตร่ตรองเราสามารถเรียกใช้เมธอดที่รันไทม์โดยไม่คำนึงถึงตัวระบุการเข้าถึงที่ใช้กับพวกเขา

java.langและjava.lang.reflectแพคเกจให้ชั้นเรียนสำหรับการสะท้อนจาวา

การสะท้อนสามารถใช้เพื่อรับข้อมูลเกี่ยวกับ -

  1. ระดับgetClass()วิธีการที่ใช้ในการรับชื่อของคลาสที่เป็นวัตถุ

  2. ก่อสร้างgetConstructors()วิธีการที่ใช้ในการรับก่อสร้างของประชาชนในระดับที่เป็นวัตถุ

  3. วิธีการgetMethods()วิธีการที่ใช้ในการรับวิธีการสาธารณะของชั้นเรียนที่เป็นวัตถุ

สะท้อน APIส่วนใหญ่จะใช้ใน:

IDE (สภาพแวดล้อมการพัฒนาแบบรวม) เช่น Eclipse, MyEclipse, NetBeans ฯลฯ
เครื่องมือดีบั๊กและเครื่องมือทดสอบ ฯลฯ

ข้อดีของการใช้ Reflection:

คุณสมบัติ Extensibility:แอปพลิเคชันอาจใช้คลาสภายนอกที่ผู้ใช้กำหนดโดยการสร้างอินสแตนซ์ของวัตถุ Extensibility โดยใช้ชื่อที่ผ่านการรับรอง

เครื่องมือดีบั๊กและการทดสอบ: เครื่องมือดีบั๊กใช้คุณสมบัติการสะท้อนเพื่อตรวจสอบสมาชิกส่วนตัวในคลาส

ข้อเสีย:

ค่าใช้จ่ายในการปฏิบัติงาน:การดำเนินการไตร่ตรองมีประสิทธิภาพการทำงานช้ากว่าคู่ที่ไม่ได้สะท้อนแสงและควรหลีกเลี่ยงในส่วนของรหัสซึ่งถูกเรียกใช้บ่อยในแอปพลิเคชันที่ไวต่อประสิทธิภาพ

การเปิดเผยของคนในวง:รหัสไตร่ตรองแบ่งนามธรรมและอาจเปลี่ยนพฤติกรรมด้วยการอัพเกรดของแพลตฟอร์ม

Ref: Java Reflection javarevisited.blogspot.in


4
ฉันจะเพิ่มข้อเสียเปรียบ " มันแบ่ง refactoring " สำหรับฉันนั่นเป็นเหตุผลหลักที่จะหลีกเลี่ยงการไตร่ตรองให้มากที่สุด
SantiBailors

ดังนั้นจึงช่วยให้เรา (ตัวอย่าง) ตรวจสอบชั้นเรียนที่เรามี (ไม่ว่าเราจะมีกรณีของพวกเขาหรือไม่) ถูกต้อง? โดยวิธีนี้ฉันได้รับวิธีการหรือตัวสร้างของพวกเขาและใช้พวกเขาเพื่อสร้างอินสแตนซ์ใหม่ / เรียกพวกเขา ทำไมเราถึงพูดว่า "การเปลี่ยนแปลงพฤติกรรมของโปรแกรม" ถ้าพฤติกรรมนั้นมีอยู่แล้ว แต่ใช้รหัสต่างกัน? ทำไมจึงเรียกว่า "การสะท้อน" ขอบคุณ
Fernando Gabrieli

15

ตามความเข้าใจของฉัน:

Reflection อนุญาตให้โปรแกรมเมอร์เข้าถึงเอนทิตีในโปรแกรมแบบไดนามิก คือในขณะที่การเขียนโปรแกรมประยุกต์หากโปรแกรมเมอร์ไม่ทราบเกี่ยวกับคลาสหรือวิธีการของมันเขาสามารถใช้ประโยชน์จากคลาสดังกล่าวแบบไดนามิก (ในเวลาทำงาน) โดยใช้การสะท้อน

มันถูกใช้บ่อยในสถานการณ์ที่มีการเปลี่ยนชื่อคลาสบ่อยๆ หากสถานการณ์ดังกล่าวเกิดขึ้นก็มีความซับซ้อนสำหรับโปรแกรมเมอร์ที่จะเขียนใบสมัครใหม่และเปลี่ยนชื่อของคลาสอีกครั้งและอีกครั้ง

แต่โดยใช้การสะท้อนกลับมีความจำเป็นต้องกังวลเกี่ยวกับชื่อคลาสที่อาจเปลี่ยนแปลง


15

Reflection เป็นชุดของฟังก์ชั่นที่ช่วยให้คุณสามารถเข้าถึงข้อมูลรันไทม์ของโปรแกรมของคุณและแก้ไขพฤติกรรม (โดยมีข้อ จำกัด บางอย่าง)

มีประโยชน์เพราะช่วยให้คุณสามารถเปลี่ยนพฤติกรรมรันไทม์ขึ้นอยู่กับข้อมูลเมตาของโปรแกรมของคุณนั่นคือคุณสามารถตรวจสอบประเภทการคืนของฟังก์ชั่นและเปลี่ยนวิธีการจัดการสถานการณ์

ใน C # ตัวอย่างเช่นคุณสามารถโหลดชุดประกอบ (a .dll) ในรันไทม์ตรวจสอบแล้วนำทางผ่านชั้นเรียนและดำเนินการตามสิ่งที่คุณพบ นอกจากนี้ยังให้คุณสร้างอินสแตนซ์ของคลาสบนรันไทม์เรียกใช้เมธอดและอื่น ๆ

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


11

ฉันแค่ต้องการเพิ่มบางจุดให้กับทุกสิ่งที่อยู่ในรายการ

ด้วยReflection APIคุณสามารถเขียนtoString()วิธีการสากลสำหรับวัตถุใด ๆ

มันมีประโยชน์ในการแก้ไขข้อบกพร่อง

นี่คือตัวอย่าง:

class ObjectAnalyzer {

   private ArrayList<Object> visited = new ArrayList<Object>();

   /**
    * Converts an object to a string representation that lists all fields.
    * @param obj an object
    * @return a string with the object's class name and all field names and
    * values
    */
   public String toString(Object obj) {
      if (obj == null) return "null";
      if (visited.contains(obj)) return "...";
      visited.add(obj);
      Class cl = obj.getClass();
      if (cl == String.class) return (String) obj;
      if (cl.isArray()) {
         String r = cl.getComponentType() + "[]{";
         for (int i = 0; i < Array.getLength(obj); i++) {
            if (i > 0) r += ",";
            Object val = Array.get(obj, i);
            if (cl.getComponentType().isPrimitive()) r += val;
            else r += toString(val);
         }
         return r + "}";
      }

      String r = cl.getName();
      // inspect the fields of this class and all superclasses
      do {
         r += "[";
         Field[] fields = cl.getDeclaredFields();
         AccessibleObject.setAccessible(fields, true);
         // get the names and values of all fields
         for (Field f : fields) {
            if (!Modifier.isStatic(f.getModifiers())) {
               if (!r.endsWith("[")) r += ",";
               r += f.getName() + "=";
               try {
                  Class t = f.getType();
                  Object val = f.get(obj);
                  if (t.isPrimitive()) r += val;
                  else r += toString(val);
               } catch (Exception e) {
                  e.printStackTrace();
               }
            }
         }
         r += "]";
         cl = cl.getSuperclass();
      } while (cl != null);

      return r;
   }    
}

11

การสะท้อนแสงคือการให้วัตถุมองเห็นรูปร่างของมัน ข้อโต้แย้งนี้ดูเหมือนจะไม่เกี่ยวกับการไตร่ตรอง ในความเป็นจริงนี่คือความสามารถ "ระบุตัวตน"

การสะท้อนความเห็นนั้นเป็นคำศัพท์สำหรับภาษาที่ขาดความสามารถในการรู้และเข้าใจตนเองเช่น Java และ C # เนื่องจากพวกเขาไม่มีความสามารถในตนเองรู้เมื่อเราต้องการสังเกตว่ามันดูเหมือนเราจะต้องมีสิ่งอื่นเพื่อสะท้อนให้เห็นว่ามันดูเหมือน ภาษาไดนามิกที่ยอดเยี่ยมเช่น Ruby และ Python สามารถรับรู้ถึงการสะท้อนของตนเองโดยไม่ได้รับความช่วยเหลือจากบุคคลอื่น เราสามารถพูดได้ว่าวัตถุของ Java ไม่สามารถรับรู้ว่ามันดูเหมือนไม่มีกระจกซึ่งเป็นวัตถุของระดับการสะท้อน แต่วัตถุใน Python สามารถรับรู้ได้โดยไม่ต้องสะท้อน นั่นคือสาเหตุที่เราต้องการภาพสะท้อนใน Java


ประเภท (), isinstance (), callable (), dir () และ getattr () .... นี่คือการสะท้อนกลับแบบ
ไพทอน

9

จากหน้าเอกสาร Java

java.lang.reflectแพคเกจให้คลาสและอินเทอร์เฟซสำหรับการรับข้อมูลที่สะท้อนเกี่ยวกับคลาสและวัตถุ การสะท้อนกลับช่วยให้สามารถเข้าถึงข้อมูลเกี่ยวกับฟิลด์วิธีการและตัวสร้างของคลาสที่โหลดโดยใช้โปรแกรม

AccessibleObjectช่วยให้การปราบปรามการตรวจสอบการเข้าถึงถ้าจำเป็นReflectPermissionสามารถใช้ได้

เรียนในแพคเกจนี้พร้อมกับjava.lang.Classรองรับการใช้งานเช่น debuggers ล่ามตรวจวัตถุเบราว์เซอร์ชั้นเรียนและการบริการเช่นObject SerializationและJavaBeansว่าการเข้าถึงความต้องการทั้งสมาชิกสาธารณะของวัตถุเป้าหมาย (ขึ้นอยู่กับระดับรันไทม์ของมัน) หรือสมาชิกประกาศโดย ชั้นเรียนที่กำหนด

มันมีฟังก์ชั่นดังต่อไปนี้

  1. ได้รับวัตถุคลาส
  2. การตรวจสอบคุณสมบัติของคลาส (เขตข้อมูลวิธีการตัวสร้าง)
  3. การตั้งค่าและรับค่าฟิลด์
  4. วิธีการเรียก
  5. การสร้างอินสแตนซ์ใหม่ของวัตถุ

ดูที่ลิงค์เอกสารนี้สำหรับวิธีการที่เปิดเผยโดยClassคลาส

จากบทความนี้ (โดย Dennis Sosnoski ประธาน Sosnoski Software Solutions, Inc) และบทความ (security-explorations pdf):

ฉันเห็นข้อเสียมากกว่าการใช้ Reflection

ผู้ใช้การสะท้อนกลับ:

  1. มันมีวิธีที่หลากหลายมากในการเชื่อมโยงส่วนประกอบของโปรแกรมแบบไดนามิก
  2. มันมีประโยชน์สำหรับการสร้างไลบรารีที่ทำงานกับวัตถุด้วยวิธีทั่วไปมาก

ข้อเสียของการสะท้อน:

  1. การสะท้อนนั้นช้ากว่ารหัสโดยตรงเมื่อใช้สำหรับการเข้าถึงภาคสนามและวิธีการ
  2. มันสามารถปิดบังสิ่งที่เกิดขึ้นจริงในรหัสของคุณ
  3. มันข้ามรหัสที่มาสามารถสร้างปัญหาการบำรุงรักษา
  4. รหัสการสะท้อนยังมีความซับซ้อนมากกว่ารหัสโดยตรงที่เกี่ยวข้อง
  5. อนุญาตการละเมิดข้อ จำกัด ด้านความปลอดภัย Java ที่สำคัญเช่นการป้องกันการเข้าถึงข้อมูลและความปลอดภัยของประเภท

การละเมิดทั่วไป:

  1. การโหลดคลาสที่ จำกัด
  2. การรับการอ้างอิงถึงตัวสร้างวิธีการหรือสาขาของคลาสที่ถูก จำกัด
  3. การสร้างอินสแตนซ์ของวัตถุใหม่การเรียกใช้เมธอดการรับหรือการตั้งค่าฟิลด์ของคลาสที่ถูก จำกัด

ดูคำถาม SE นี้เกี่ยวกับการใช้คุณลักษณะการสะท้อนกลับที่ไม่เหมาะสม:

ฉันจะอ่านฟิลด์ส่วนตัวใน Java ได้อย่างไร

สรุป:

การใช้งานที่ไม่ปลอดภัยของฟังก์ชั่นดำเนินการจากภายในรหัสระบบยังสามารถนำไปสู่การประนีประนอมของโหมดความปลอดภัยชวาลิตร ดังนั้นใช้คุณสมบัตินี้เท่าที่จำเป็น


วิธีหนึ่งในการหลีกเลี่ยงปัญหาประสิทธิภาพการทำงานของ Reflection ในบางกรณีคือให้ชั้นเรียนWoozleตรวจสอบคลาสอื่น ๆ เมื่อเริ่มต้นเพื่อดูว่ามีRegisterAsWoozleHelper()วิธีคงที่และเรียกใช้วิธีดังกล่าวทั้งหมดที่พบด้วยการโทรกลับที่พวกเขาสามารถใช้เพื่อบอกWoozleตัวเอง จำเป็นต้องใช้การสะท้อนในขณะที่เช่นข้อมูลที่ดีซีเรียลไลซ์
supercat

9

ตามชื่อตัวเองแนะนำว่ามันสะท้อนให้เห็นถึงสิ่งที่มันถือตัวอย่างวิธีการเรียน ฯลฯ นอกเหนือจากการให้คุณสมบัติในการเรียกใช้วิธีการสร้างตัวอย่างแบบไดนามิกที่รันไทม์

มันถูกใช้โดยกรอบและแอพพลิเคชั่นมากมายภายใต้เนื้อไม้เพื่อเรียกใช้บริการโดยไม่ต้องรู้รหัส


7

Reflection ช่วยให้คุณสามารถเขียนโค้ดทั่วไปได้มากขึ้น อนุญาตให้คุณสร้างวัตถุที่รันไทม์และเรียกใช้เมธอดของมันที่รันไทม์ ดังนั้นโปรแกรมสามารถทำพารามิเตอร์สูง นอกจากนี้ยังช่วยให้ตรวจสอบวัตถุและชั้นเรียนเพื่อตรวจสอบตัวแปรและวิธีการที่สัมผัสกับโลกภายนอก


6

Reflectionมีประโยชน์หลายอย่าง สิ่งที่ฉันคุ้นเคยมากกว่าคือการสร้างรหัสได้อย่างรวดเร็ว

IE: คลาสแบบไดนามิก, ฟังก์ชั่น, คอนสตรัคเตอร์ - ขึ้นอยู่กับข้อมูลใด ๆ (ผลลัพธ์ xml / array / sql / hardcoded / etc .. )


1
คำตอบนี้จะมากดีกว่าถ้าคุณให้เพียงตัวอย่างหนึ่งที่ผิดปกติของรหัสที่สร้างขึ้นทั้งจากผล SQL หรือไฟล์ XML ฯลฯ
ThisClark

ไม่มีปัญหา. ฉันใช้การไตร่ตรองในแอปพลิเคชัน windows ที่สร้างอินเตอร์เฟสแบบไดนามิกโดยยึดตาม XML ที่นำมาจากฐานข้อมูล
Ess Kay

โดยพื้นฐานแล้วมีคลาสที่ฉันสร้างขึ้นซึ่งแสดงรายงานผู้ใช้ รายงานนี้มีพารามิเตอร์เช่นวันที่ (จากถึง) id หรืออย่างอื่น ข้อมูลนี้ถูกเก็บไว้ใน xml ดังนั้นก่อนอื่นเรามีการเลือกรายงาน ตามรายงานที่เลือกแบบฟอร์มจะได้รับ xml เมื่อดึง xml แล้วจะใช้การสะท้อนเพื่อสร้างคลาสที่มีเขตข้อมูลตามชนิดที่สะท้อน เมื่อคุณเปลี่ยนเป็นรายงานอื่นกระดานชนวนจะถูกล้างข้อมูลและจะสร้างฟิลด์ใหม่โดยอิงตาม xml ดังนั้นรูปแบบไดนามิกจึงเป็นไปตามการสะท้อนกลับ ฉันใช้ในวิธีอื่น ๆ แต่นี่ควรจะเป็นความหวังที่พอเพียงที่จะช่วยได้
Ess Kay

3

ฉันต้องการตอบคำถามด้วยตัวอย่าง Hibernateโครงการแรกทั้งหมดใช้Reflection APIเพื่อสร้างCRUDคำสั่งเพื่อเชื่อมช่องว่างระหว่างแอปพลิเคชันที่รันอยู่กับที่เก็บข้อมูล เมื่อสิ่งต่าง ๆ เปลี่ยนไปในโดเมนสิ่งที่Hibernateต้องรู้ก็คือพวกมันจะยังคงอยู่ในแหล่งข้อมูลและในทางกลับกัน

หรือใช้งานLombok Projectได้ มันเป็นเพียงการฉีดรหัสในเวลารวบรวมผลในการแทรกรหัสลงในชั้นเรียนโดเมนของคุณ (ฉันคิดว่ามันก็โอเคสำหรับผู้ได้รับและ setters)

Hibernateเลือกreflectionเนื่องจากมีผลกระทบน้อยที่สุดต่อกระบวนการสร้างสำหรับแอปพลิเคชัน

และจาก Java 7 เรามีMethodHandlesซึ่งใช้งานReflection APIได้ดี ในโครงการเพื่อทำงานกับตัวบันทึกเราเพียงคัดลอกโค้ดถัดไป:

Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());

เพราะมันยากที่จะพิมพ์ผิดในกรณีนี้


3

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

ตัวอย่างที่เป็นประโยชน์ของการใช้การสะท้อนจะเป็น Java Language Server ที่เขียนใน Java หรือ PHP Language Server ที่เขียนใน PHP และอื่น ๆ Language Server ให้ความสามารถ IDE ของคุณเช่นการเติมข้อความอัตโนมัติข้ามไปที่การกำหนดคำอธิบายบริบทช่วยเหลือ เพื่อให้มีชื่อแท็กทั้งหมด (คำที่สามารถเติมข้อความอัตโนมัติ) เพื่อแสดงการจับคู่ที่เป็นไปได้ทั้งหมดในขณะที่คุณพิมพ์เซิร์ฟเวอร์ภาษาจะต้องตรวจสอบทุกอย่างเกี่ยวกับชั้นเรียนรวมถึงบล็อก doc และสมาชิกส่วนตัว เพื่อที่จะต้องมีภาพสะท้อนของชั้นเรียนดังกล่าว

ตัวอย่างอื่นจะเป็นการทดสอบหน่วยของวิธีการส่วนตัว วิธีหนึ่งในการทำเช่นนั้นคือการสร้างภาพสะท้อนและเปลี่ยนขอบเขตของวิธีการสู่สาธารณะในขั้นตอนการตั้งค่าการทดสอบ แน่นอนว่าคนหนึ่งสามารถโต้แย้งวิธีส่วนตัวไม่ควรทดสอบโดยตรง แต่นั่นไม่ใช่ประเด็น

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