1. บทนำ
Java Reflection เป็นกลไกที่ช่วยให้เราได้รับข้อมูลภายในของวิธีการคลาสคุณสมบัติคลาสพาเรนต์อินเทอร์เฟซ ฯลฯ ที่รันไทม์ กล่าวอีกนัยหนึ่งการสะท้อนเป็นกระบวนการ "ย้อนกลับ" เป็นหลัก เมื่อเราสร้างอินสแตนซ์ของคลาสผ่าน new มันถูกสร้างขึ้นจริงโดยเครื่องเสมือน Java ตามวัตถุ Class ของคลาสนี้ที่รันไทม์และการสะท้อนคือการรับข้อมูลคำจำกัดความผ่านวัตถุ Class ของคลาสเพื่อให้เราสามารถเข้าถึงคุณสมบัติและวิธีการรู้คลาสแม่ของคลาสนี้
2. ชั้นเรียน
เรารู้ว่าการใช้ Javac สามารถรวบรวมไฟล์. java ลงในไฟล์. class ซึ่งมีข้อมูลคำจำกัดความดั้งเดิมของเราสำหรับคลาส (คลาสแม่, อินเตอร์เฟส, คอนสตรัคเตอร์, คุณสมบัติ, วิธีการ ฯลฯ ) ไฟล์. class จะถูกโหลดลงใน Java Virtual Machine (JVM) ClassLoader ที่รันไทม์ เมื่อโหลดไฟล์. class JVM จะสร้างวัตถุคลาสสำหรับมัน วัตถุที่เราสร้างอินสแตนซ์ผ่านใหม่ในโปรแกรมจะถูกสร้างขึ้นตามวัตถุคลาสที่สอดคล้องกันที่รันไทม์ เพื่อความแม่นยำวัตถุคลาสนี้เป็นตัวอย่างของ java.lang.Class<T> คลาสทั่วไป ตัวอย่างเช่นวัตถุ Class<MyClass> เป็นอินสแตน Class<T> ที่ห่อหุ้มข้อมูลคำจำกัดความของคลาส MyClass เนื่องจากคลาส java.lang.Class<T> ไม่มีตัวสร้างสาธารณะเราจึงไม่สามารถยกตัวอย่างคลาสนี้ได้โดยตรง เราสามารถรับวัตถุคลาสผ่านวิธีการต่อไปนี้
ในคำอธิบายต่อไปนี้เราจะเข้าชั้นเรียนและชั้นเรียนนักเรียนเป็นตัวอย่าง:
คนชั้นเรียนสาธารณะ {ชื่อสตริงส่วนตัว; อายุ int ส่วนตัว; คนสาธารณะ (ชื่อสตริงอายุ int) {this.name = ชื่อ; this.age = อายุ; } public int getage () {return Age; } สตริงสาธารณะ getName () {ชื่อคืน; } การตั้งค่าโมฆะสาธารณะ (อายุ int) {this.age = อายุ; } โมฆะสาธารณะ setName (ชื่อสตริง) {this.name = name; } โมฆะสาธารณะพูด () {system.out.println (getName () + "" + getage ()); }} นักเรียนชั้นเรียนสาธารณะขยายคน {เกรดส่วนตัวส่วนตัว; นักเรียนสาธารณะ (ชื่อสตริงอายุ int) {super (ชื่ออายุ); } นักเรียนสาธารณะ (ชื่อสตริงอายุ int เกรด int) {super (ชื่ออายุ); this.grade = เกรด; } public int getGrade () {ส่งคืนเกรด; } โมฆะสาธารณะ setGrade (เกรด int) {this.grade = เกรด; } โมฆะส่วนตัวเรียนรู้ (หลักสูตรสตริง) {system.out.println (ชื่อ + "เรียนรู้" + หลักสูตร); - รับวัตถุคลาสตามชื่อคลาส
หากเรารู้ชื่อของชั้นเรียนในช่วงระยะเวลาการรวบรวมเราจะได้รับวัตถุคลาสเช่นนี้:
ชั้นเรียน <people> peopleclass = people.class;
นอกจากนี้ยังมีวิธีการรับวัตถุคลาสตามชื่อเส้นทางเต็มของคลาสดังนี้:
// สมมติว่าคลาสผู้คนอยู่ในคลาสแพ็คเกจ com.test <people> peopleclass = class.forname ("com.test.people"); โปรดทราบว่าพารามิเตอร์ของเมธอด Class.forName() จะต้องเป็นชื่อเส้นทางเต็มของคลาส ในความเป็นจริงตราบใดที่เรา "นำเข้า com.test.people" เราสามารถรับวัตถุคลาสของมันโดยตรงผ่าน " People.class " โดยไม่ต้องเขียนเส้นทางเต็ม (หากไม่พบคลาสที่สอดคล้องกันใน classpath เมื่อเรียกเมธอด Class.forName() , ClassNotFoundException จะถูกโยนลงไป)
รับวัตถุคลาสผ่านวัตถุเอง
คนคน = คนใหม่ ("บิล", 18); ชั้นเรียน <people> peopleclass = people.getClass (); รับตัวสร้างของชั้นเรียนโดยการสะท้อนกลับ
เมื่อเราได้รับวัตถุคลาสของ People แล้วเราสามารถรับข้อมูลคำจำกัดความดั้งเดิมของชั้นเรียน People ผ่านวัตถุคลาสนี้ ก่อนอื่นมารับวัตถุตัวสร้างของคลาส People กันเถอะ ด้วยวัตถุตัวสร้างนี้เราสามารถสร้างวัตถุ People ตัวอย่างเช่นเราสามารถเพิ่มรหัสต่อไปนี้ใน student.java:
โมฆะคงที่สาธารณะหลัก (String [] args) {คลาส <people> pclass = people.class; ลอง {constructor <people> constructor = pclass.getConstructor (string.class, int.class); คนคน = constructor.newinstance ("บิล", 18); obj.speak (); } catch (exception e) {}} ในด้านบนเราเรียกวิธี getConstructor เพื่อรับวัตถุตัวสร้างของคลาส People เนื่องจากตัวสร้างเราต้องการได้รับพารามิเตอร์อย่างเป็นทางการของ String ประเภทและ int เราผ่าน String.class และ int.class ด้วยวัตถุคอนสตรัคเตอร์เราสามารถเรียกใช้วิธี newInstance เพื่อสร้างวัตถุ people
โปรดทราบว่าเมื่อ Constructor Method และ Field ของคลาสได้รับผ่านการสะท้อนกลับก่อนที่จะเรียกวิธีการของวัตถุเหล่านี้ธง accessible ของวัตถุนี้ถูกตั้งค่าเป็น true เพื่อยกเลิกการตรวจสอบการเข้าถึงภาษา Java ซึ่งสามารถปรับปรุงความเร็วในการสะท้อนกลับ ดังที่แสดงในรหัสต่อไปนี้:
Constructor <People> constructor = peopleClass.getConstructor (string.class, int.class); // ตั้งค่าคุณสมบัติที่เข้าถึงได้ของตัวสร้างเป็น ture เพื่อยกเลิกการตรวจสอบการเข้าถึง Java constructor.setAccessible (จริง);
การได้รับวิธีการประกาศในชั้นเรียนผ่านการสะท้อนกลับ
รับวิธีการที่ประกาศในคลาสปัจจุบัน (ไม่รวมสืบทอดมาจากคลาสแม่)
ในการรับวิธีการทั้งหมดที่ประกาศในคลาสปัจจุบันคุณสามารถใช้ฟังก์ชัน getDeclaredMethods ในชั้นเรียน มันจะได้รับวิธีการทั้งหมดที่ประกาศในชั้นเรียนปัจจุบัน (รวมถึง private public static และวิธีอื่น ๆ ) มันจะส่งคืนอาร์เรย์ของวัตถุ Method และแต่ละวัตถุ Method การแสดงถึงวิธีที่ประกาศในชั้นเรียน ในการรับวิธีการที่ระบุคุณสามารถเรียก getDeclaredMethod(String name, Class...<T> parameterTypes)
ดังที่แสดงในรหัสต่อไปนี้:
โมฆะคงที่ส่วนตัว showdeclaredMethods () {นักเรียนนักเรียน = นักเรียนใหม่ ("บิล", 18); // รับวิธีการทั้งหมดที่ประกาศโดยวิธีชั้นเรียนนักเรียน [] วิธี = student.getClass (). getDeclaredMethods (); ลอง {// รับ Object LearnMethod (ห่อหุ้มวิธีการเรียนรู้) วิธี LearnMethod = Student.getClass (). getDeclaredMethod ("เรียนรู้", string.class); // รับรายการพารามิเตอร์ของวิธีการเรียนรู้และพิมพ์ออกมาคลาส <?> [] paramclasses = learnMethod.getParameterTypes (); สำหรับ (คลาส <?> คลาส: paramclasses) {system.out.println ("เรียนรู้เมธอดพารามิเตอร์:" + class.getName ()); } // ตัดสินว่าวิธีการเรียนรู้เป็น System.out.out.println (LearnMethod.getName () + "เป็นส่วนตัว" + modifier.isprivate (LearnMethod.getModifiers ()); // โทรหาวิธีการเรียนรู้ LearnMethod.invoke (นักเรียน, "Java Reflection"); } catch (exception e) {}} รับวิธีการสาธารณะที่ประกาศในชั้นเรียนปัจจุบันและคลาสแม่
ในการรับคลาสปัจจุบันและวิธีการ public ทั้งหมดที่ประกาศไว้ในชั้นเรียนหลักคุณสามารถเรียกฟังก์ชัน getMethods และเพื่อรับวิธี public ที่ระบุคุณสามารถเรียกวิธี getMethod โปรดดูรหัสต่อไปนี้:
โมฆะแบบคงที่ส่วนตัวแสดงให้เห็นถึง () {นักเรียนนักเรียน = นักเรียนใหม่ ("Mr.Simple"); // รับวิธีการสาธารณะทั้งหมด (รวมถึงนักเรียนและสืบทอดมาจากชั้นเรียนผู้ปกครอง) วิธี [] วิธี = student.getClass (). getMethods (); ลอง {// โปรดทราบว่าเฉพาะวิธีการสาธารณะเท่านั้นที่สามารถรับได้ผ่าน getMethod หากคุณพยายามที่จะได้รับวิธีส่วนตัวข้อยกเว้นจะถูกโยนลงไป Method LearnMethod = Student.getClass (). getMethod ("เรียนรู้", string.class); } catch (exception e) {}} รับแอตทริบิวต์ที่กำหนดไว้ในชั้นเรียนโดยการสะท้อนกลับ
การรับแอตทริบิวต์นั้นคล้ายคลึงกับการรับวิธียกเว้นว่าวิธีการโทรไปยัง getMethods() / getDeclaredMethods() จะถูกแทนที่ด้วยวิธีการโทรไปยัง getFields() / getDeclaredFields()
รับแอตทริบิวต์ที่กำหนดไว้ในคลาสปัจจุบัน (ไม่รวมแอตทริบิวต์ที่สืบทอดมาจากคลาสแม่)
เพื่อให้ได้แอตทริบิวต์ทั้งหมดที่กำหนดไว้ในคลาสปัจจุบัน (รวมถึงคุณลักษณะต่าง ๆ เช่น private public static ฯลฯ ) คุณสามารถเรียกฟังก์ชัน getDeclaredFields ของวัตถุคลาส; ในการรับแอตทริบิวต์ที่ระบุคุณสามารถโทรหา getDeclaredField
ดังที่แสดงในรหัสต่อไปนี้:
โมฆะคงที่ส่วนตัว showdeclaredfields () {นักเรียนนักเรียน = นักเรียนใหม่ ("บิล", 18); // รับแอตทริบิวต์ทั้งหมดที่กำหนดไว้ในฟิลด์คลาสปัจจุบัน [] ฟิลด์ = Student.getClass (). getDeclaredFields (); ลอง {// รับแอตทริบิวต์ที่ระบุ Field Field = Student.getClass (). getDeclaredField ("เกรด"); // รับ Attribute Value System.out.println ("เกรดคือ:" + gradefield.getint (นักเรียน)); // ตั้งค่าแอตทริบิวต์ค่า grade.set (นักเรียน, 10); } catch (exception e) {}} รับคุณลักษณะสาธารณะที่กำหนดไว้ในคลาสปัจจุบันและคลาสแม่
เพื่อให้ได้คุณสมบัติ public ทั้งหมดที่กำหนดไว้ในคลาสปัจจุบันและคลาสหลักคุณสามารถเรียกฟังก์ชัน getFields ของวัตถุ Class ในการรับทรัพย์สิน public ที่ระบุคุณสามารถโทรหาวิธี getField ดังที่แสดงในรหัสต่อไปนี้:
Private Static Void Showfields () {นักเรียนนักเรียน = นักเรียนใหม่ ("บิล", 18); // รับคุณสมบัติสาธารณะทั้งหมดของชั้นเรียนและชั้นเรียนปัจจุบัน [] publicfields = student.getClass (). getFields (); - การสะท้อนกลับเพื่อให้ได้คลาสแม่ของคลาสและอินเทอร์เฟซที่ดำเนินการโดยคลาส
รับคลาสหลัก
เพียงเรียกใช้วิธี getSuperClass ของวัตถุ Class ดังที่แสดงในรหัสต่อไปนี้:
นักเรียนนักเรียน = นักเรียนใหม่ ("บิล", 18); ชั้นเรียน <?> superclass = student.getClass (). getSuperClass (); รับอินเทอร์เฟซที่ใช้งาน
หากต้องการทราบว่าคลาสใดที่คลาสใช้งานเพียงแค่เรียกใช้วิธี getInterfaces ของวัตถุ Class ดังที่แสดงในรหัสต่อไปนี้:
Void Private Void Showinterfaces () {นักเรียนนักเรียน = นักเรียนใหม่ ("บิล", 19); คลาส <?> [] อินเทอร์เฟซ = student.getClass (). getInterfaces ();}สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาและการทำงานของทุกคน