เรียกใช้วิธีการคงที่โดยใช้การสะท้อน


199

ฉันต้องการที่จะเรียกใช้mainวิธีการซึ่งเป็นแบบคงที่ ฉันได้รับประเภทของวัตถุClassแต่ฉันไม่สามารถสร้างตัวอย่างของคลาสนั้นและยังไม่สามารถเรียกใช้staticเมธอดmainได้

คำตอบ:


291
// String.class here is the parameter type, that might not be the case with you
Method method = clazz.getMethod("methodName", String.class);
Object o = method.invoke(null, "whatever");

ในกรณีที่วิธีการใช้งานส่วนตัวแทนgetDeclaredMethod() getMethod()และเรียกใช้setAccessible(true)บนเมธอด object


49

จาก Javadoc ของ Method.invoke ():

หากวิธีการพื้นฐานเป็นแบบคงที่แล้วอาร์กิวเมนต์ obj ที่ระบุจะถูกละเว้น อาจเป็นโมฆะ

จะเกิดอะไรขึ้นเมื่อคุณ

คลาสคลาส = ... ;
วิธีการ m = klass.getDeclaredMethod (methodName, paramtypes);
m.invoke (null, args)

14
String methodName= "...";
String[] args = {};

Method[] methods = clazz.getMethods();
for (Method m : methods) {
    if (methodName.equals(m.getName())) {
        // for static methods we can use null as instance of class
        m.invoke(null, new Object[] {args});
        break;
    }
}

11
ทำไมไม่ใช้ getMethod ด้วยชื่อที่ถูกต้องแทนที่จะวนซ้ำทุกวิธี
mjaggard

11
บางครั้งการวนซ้ำง่ายกว่าและค้นหาวิธีโดยใช้ชื่อมากกว่าการใช้ getMethod เนื่องจาก getMethod (หรือ getDeclaredMethod) ต้องการให้คุณทำงานกับชนิดพารามิเตอร์โดยละเอียด ขึ้นอยู่กับว่าประสิทธิภาพของไมโครมีน้อยหรือไม่ - การทำซ้ำ Java นั้นรวดเร็วมากดังนั้นหากคุณไม่เรียกใช้วิธีการนับล้านครั้งในการวนรอบภายในการทำซ้ำจะเร็วพอ
Tony Eastwood

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

4
จะมีช่วงเวลาที่ไม่ดีด้วยวิธีการโอเวอร์โหลด
Ulysse Mizrahi

1
@ UlysseMizrahi ทุกอย่างขึ้นอยู่กับสิ่งที่คุณจับคู่ แต่ใช่ถ้าคุณกำลังเขียนรหัสห้องสมุดมันอาจเป็นอันตรายได้เพียงพึ่งพาชื่อ ฉันมักจะตรวจสอบคำอธิบายประกอบที่เฉพาะเจาะจงหรือลายเซ็นวิธีการเฉพาะเช่น "วิธีการคงที่ใช้ String และส่งกลับตัวอย่างของชั้นเรียน" จากนั้นยืนยันว่ามีวิธีการดังกล่าวพบเพียงหนึ่งเดียว
cobbzilla

0
public class Add {
    static int add(int a, int b){
        return (a+b);
    }
}

ในตัวอย่างข้างต้น 'เพิ่ม' เป็นวิธีคงที่ที่ใช้จำนวนเต็มสองเป็นอาร์กิวเมนต์

ตัวอย่างต่อไปนี้ใช้เรียกวิธีการ 'เพิ่ม' ด้วยอินพุต 1 และ 2

Class myClass = Class.forName("Add");
Method method = myClass.getDeclaredMethod("add", int.class, int.class);
Object result = method.invoke(null, 1, 2);

การอ้างอิงการเชื่อมโยง

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