2011-01-22 16 views
47

मैं एक निजी स्थैतिक विधि का आह्वान करना चाहता हूं। मेरा नाम है मैंने सुना है कि इसे जावा प्रतिबिंब तंत्र का उपयोग करके किया जा सकता है। मैं यह कैसे कर सकता हूं?प्रतिबिंब (जावा) का उपयोग करके मैं एक निजी स्थैतिक विधि कैसे शुरू करूं?

संपादित करें: विधि का आह्वान करने का प्रयास करते समय मुझे मिली एक समस्या यह है कि इसके तर्क के प्रकार को कैसे निर्दिष्ट किया जाए। मेरी विधि एक तर्क प्राप्त करती है और इसका प्रकार मानचित्र है। इसलिए मैं Map<User, String>.TYPE नहीं कर सकता (रन टाइम में जावा टाइप एरर की वजह से मानचित्र जैसी कोई चीज़ नहीं है)। विधि पाने के लिए कोई और तरीका है?

+1

कोशिश 'MyClass.class.getDeclaredMethod (" MyMethod ", Map.class);' अपने मामले – Cratylus

+0

काफी मजेदार है सामान्य के लिए विधि की जानकारी अभी भी रनटाइम पर उपलब्ध है। 'Method.getGeneric पैरामीटर प्रकार –

उत्तर

79

मान लें कि आप MyClass.myMethod (int x) को कॉल करना चाहते हैं;

Method m = MyClass.class.getDeclaredMethod("myMethod", Integer.TYPE); 
m.setAccessible(true); //if security settings allow this 
Object o = m.invoke(null, 23); //use null if the method is static 
+0

धन्यवाद। मेरी विधि एक पैरामीटर प्राप्त करती है और इसका प्रकार मानचित्र <उपयोगकर्ता, स्ट्रिंग> है। इसलिए मैं 'मानचित्र <उपयोगकर्ता, स्ट्रिंग> .TYPE' नहीं कर सकता। विधि पाने के लिए कोई और तरीका है? – snakile

+6

@snakile: 'MyClass.class.getDeclaredMethod ("myMethod", Map.class) को आजमाएं; 'आपके मामले के लिए – Cratylus

+3

जो कुछ भी मुझे विश्वविद्यालय में पढ़ाया गया था वह एक झूठ था ... – rsy

0
Object insecure; //This needs to be an initialized reference 

Class c = insecure.getClass(); 
Method m = c.getMethod(name, parameterTypes); //Fill the name and types in 
m.setAccessible(true); 
m.invoke(insecure, parameters); //Fill in the parameters you would like 

जांचे हुए अपवादों जो फेंक दिया जा सकता है की एक संख्या हैं। पैरामीटर प्रकार और पैरामीटर दोनों लंबवत तर्क (परिवर्तनीय लंबाई) हैं, उन्हें आवश्यकतानुसार भरें। विनिर्देशन द्वारा जेवीएम में दृढ़ता से टाइप किए गए कॉलिंग सम्मेलन हैं, इसलिए आपको पैरामीटर प्रकारों को जानने की आवश्यकता है।

इसके साथ, जब तक कि आप किसी प्रकार के एप्लिकेशन कंटेनर, सर्वर घटक कंटेनर, आरएमआई जैसी प्रणाली, या जेवीएम आधारित लैंगेज लिख रहे हैं, आपको इसे करने से बचना चाहिए। reflection tutorial

import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 
import java.util.Arrays; 

public class InvokeMain { 
    public static void main(String... args) { 
    try { 
     Class<?> c = Class.forName(args[0]); 
     Class[] argTypes = new Class[] { String[].class }; 
     Method main = c.getDeclaredMethod("main", argTypes); 
     String[] mainArgs = Arrays.copyOfRange(args, 1, args.length); 
     System.out.format("invoking %s.main()%n", c.getName()); 
     main.invoke(null, (Object)mainArgs); 

     // production code should handle these exceptions more gracefully 
    } catch (ClassNotFoundException x) { 
     x.printStackTrace(); 
    } catch (NoSuchMethodException x) { 
     x.printStackTrace(); 
    } catch (IllegalAccessException x) { 
     x.printStackTrace(); 
    } catch (InvocationTargetException x) { 
     x.printStackTrace(); 
    } 
    } 
} 
9

आह्वान मुख्य नहीं, आप Map<K,V>.class नहीं कह सकता। यह टाइप एरर के कारण है। रनटाइम पर, ऐसी कोई चीज़ नहीं है।

सौभाग्य से, आप कह सकते हैं कि केवल पुराना Map.class है। यह रनटाइम पर भी वही है।

यदि चेतावनियां आपको परेशान करती हैं, तो जेनेरिक से संबंधित अन्य प्रश्नों की खोज करें और मिटाएं टाइप करें, यहां विषय पर जानकारी का भरपूर धन है।

1

मैं एक विधि का उपयोग करता हूं जो लक्ष्य विधि प्राप्त करने और फिर इसे आमंत्रित करने के लिए समाहित करता है। निश्चित रूप से कुछ सीमाएं हैं। यहाँ विधि एक वर्ग में डाल दिया है और अपने JUnit परीक्षण:

public class Invoker { 
/** 
* Get method and invoke it. 
* 
* @author jbetancourt 
* 
* @param name of method 
* @param obj Object to invoke the method on 
* @param types parameter types of method 
* @param args to method invocation 
* @return return value 
* @throws Exception for unforseen stuff 
*/ 
public static final <T> Object invokeMethod(final String name, final T obj, 
    final Class<?>[] types, final Object... args) throws Exception { 

    Method method = obj.getClass().getDeclaredMethod(name, types); 
    method.setAccessible(true); 
    return method.invoke(obj, args); 
} 

/** 
* Embedded JUnit tests. 
*/ 
@RunWith(JUnit4.class) 
public static class InvokerTest { 
    /** */ 
    @Test 
    public void testInvoke() throws Exception { 
     class TestTarget { 
      private String hello() { 
       return "Hello world!"; 
      } 
     } 

     String actual = (String) Invoker.invokeMethod("hello", 
       new TestTarget(), new Class<?>[] {}); 
     String expected = "Hello world!"; 
     assertThat(actual, is(expected)); 

    } 
} 

}

संबंधित मुद्दे

 संबंधित मुद्दे