การเรียกใช้เมธอดและการเข้าถึงฟิลด์
เรียกเมธอด private และกำหนดค่าฟิลด์ที่เข้าถึงไม่ได้ด้วย Method.invoke และ Field.set ร่วมกับ setAccessible
การเรียกใช้เมธอดและการเข้าถึงฟิลด์ เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
setAccessible: การข้ามข้อจำกัดด้านการมองเห็น
เรียก field.setAccessible(true) หรือ method.setAccessible(true) เพื่อข้ามการควบคุมการเข้าถึงของ Java ซึ่งจำเป็นสำหรับสมาชิก private และต้องมีสิทธิ์เข้าถึงโมดูลที่เหมาะสมใน Java 9 ขึ้นไป
Field f = User.class.getDeclaredField("name");
f.setAccessible(true);
User u = new User("Alice", 30);
System.out.println(f.get(u)); // "Alice"
f.set(u, "Bob"); // mutate the private field
System.out.println(u.getName()); // "Bob"การอ่านค่าฟิลด์
ใช้ field.get(instance) เพื่ออ่านค่าฟิลด์ใด ๆ โดยค่าพื้นฐานจะถูกห่อเป็นออบเจ็กต์ สำหรับฟิลด์ static ให้ส่ง null เป็นอินสแตนซ์
Field f = MyClass.class.getDeclaredField("count");
f.setAccessible(true);
int count = (int) f.get(null); // static field → null instanceการกำหนดค่าฟิลด์
ใช้ field.set(instance, value) เพื่อเขียนค่าลงฟิลด์ ชนิดของค่าต้องตรงกันหรือสามารถแกะจากออบเจ็กต์โดยอัตโนมัติได้ การกำหนดค่าให้ฟิลด์ final ผ่านรีเฟลกชันมีพฤติกรรมที่ไม่รับประกันใน JVM สมัยใหม่
Field nameField = User.class.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(user, "Charlie");การเรียกเมธอดผ่านรีเฟลกชัน
รับออบเจ็กต์ Method เรียก setAccessible(true) แล้วเรียกใช้ด้วย method.invoke(instance, args...) ค่าที่ส่งคืนคือ Object
Method greet = User.class.getDeclaredMethod("greet", String.class);
greet.setAccessible(true);
String result = (String) greet.invoke(user, "World");
System.out.println(result);การจัดการ InvocationTargetException
หากเมธอดที่เรียกใช้โยนข้อยกเว้น รีเฟลกชันจะห่อข้อยกเว้นนั้นไว้ใน InvocationTargetException ให้แกะข้อยกเว้นออกด้วย getCause()
try {
method.invoke(obj, args);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
System.err.println("Method threw: " + cause.getMessage());
} catch (IllegalAccessException | NoSuchMethodException e) {
System.err.println("Reflection error: " + e.getMessage());
}การเรียกใช้เมธอด static
ส่ง null เป็นอาร์กิวเมนต์อินสแตนซ์เมื่อเรียกใช้เมธอด static
Method parseInt = Integer.class.getDeclaredMethod("parseInt", String.class);
int value = (int) parseInt.invoke(null, "42"); // null = static
System.out.println(value); // 42การสร้างอินสแตนซ์ผ่านคอนสตรักเตอร์
รับ Constructor เรียก setAccessible(true) สำหรับคอนสตรักเตอร์ private แล้วจึงเรียก newInstance(args...)
Constructor<User> ctor = User.class.getDeclaredConstructor(String.class, int.class);
ctor.setAccessible(true);
User u = ctor.newInstance("Diana", 28);
System.out.println(u);รีเฟลกชันในเฟรมเวิร์ก: Spring DI
สปริงใช้รีเฟลกชันเพื่อสร้างบีนและฉีดการพึ่งพา โดยเรียกใช้คอนสตรักเตอร์ private และกำหนดค่าให้ฟิลด์ private เพื่อเชื่อมโยงบริบทของแอปพลิเคชัน
การเข้าถึงโมดูลใน Java 9 ขึ้นไป
ใน Java 9 ขึ้นไป โมดูลจะจำกัด setAccessible เป็นค่าเริ่มต้น หากคลาสอยู่ในโมดูลที่มีชื่อ คุณอาจต้องเปิดแพ็กเกจด้วย --add-opens java.base/java.lang=ALL-UNNAMED
// JVM flag to open a package for reflection:
// --add-opens java.base/java.lang=ALL-UNNAMEDMethodHandles ทางเลือกที่เร็วกว่า
MethodHandles.lookup().findVirtual() ให้การเรียกใช้เมธอดแบบรีเฟลกชันที่มีประสิทธิภาพใกล้เคียงการเรียกโดยตรงหลังการปรับให้เหมาะสมของ JIT จึงเหมาะสำหรับโค้ดไลบรารีที่ให้ความสำคัญกับประสิทธิภาพ
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(User.class, MethodHandles.lookup());
MethodHandle handle = lookup.findVirtual(User.class, "getName", MethodType.methodType(String.class));
String name = (String) handle.invoke(user);แนวปฏิบัติที่ดีสำหรับรีเฟลกชัน
แคชออบเจ็กต์ Field/Method และอย่าดึงออบเจ็กต์เหล่านี้ซ้ำในลูปที่ทำงานบ่อย ห่อรีเฟลกชันไว้ในคลาสบริการ พิจารณาใช้ MethodHandles เพื่อประสิทธิภาพ และเลือกใช้อินเทอร์เฟซแทนรีเฟลกชันเมื่อทำได้
ตรวจสอบความเข้าใจ
เมื่อเมธอดที่เรียกผ่านรีเฟลกชันโยนข้อยกเว้น ข้อยกเว้นใดจะห่อสาเหตุไว้
สรุป
ใช้ setAccessible(true) เพื่อเข้าถึงสมาชิก private เรียกใช้เมธอดผ่าน method.invoke() แกะ InvocationTargetException ออก แคชออบเจ็กต์รีเฟลกชัน และเลือกใช้ MethodHandles สำหรับเส้นทางที่ทำงานบ่อย
คำถามที่พบบ่อย
บทเรียน “การเรียกใช้เมธอดและการเข้าถึงฟิลด์” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การเรียกใช้เมธอดและการเข้าถึงฟิลด์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การเรียกใช้เมธอดและการเข้าถึงฟิลด์”
เรียกเมธอด private และกำหนดค่าฟิลด์ที่เข้าถึงไม่ได้ด้วย Method.invoke และ Field.set ร่วมกับ setAccessible คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การเรียกใช้เมธอดและการเข้าถึงฟิลด์” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การตรวจสอบคลาสด้วยรีเฟลกชัน
- การเรียกใช้เมธอดและการเข้าถึงฟิลด์
- พร็อกซีแบบไดนามิกด้วย InvocationHandler
- ประสิทธิภาพของรีเฟลกชันและทางเลือกอื่น