0Pricing
Java Academy · บทเรียน

การเรียกใช้เมธอดและการเข้าถึงฟิลด์

เรียกเมธอด 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-UNNAMED

MethodHandles ทางเลือกที่เร็วกว่า

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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การตรวจสอบคลาสด้วยรีเฟลกชัน
  2. การเรียกใช้เมธอดและการเข้าถึงฟิลด์
  3. พร็อกซีแบบไดนามิกด้วย InvocationHandler
  4. ประสิทธิภาพของรีเฟลกชันและทางเลือกอื่น
← กลับไปที่ Java Academy