2011-05-28 16 views
10

मैं जावा में प्रतिबिंब का उपयोग करने की कोशिश कर रहा हूं लेकिन मुझे एक अजीब त्रुटि मिल रही है। क्या संभव मुद्दे हैं जब मैं एक त्रुटि मिलेगा जिसमें बताया गया:कॉल डायनामिक विधियों का उपयोग करते समय IllegalAccessException

java.lang.IllegalAccessException: Class com.myapp.core.utils.EventDispatcher can not access a member of class appApp$1 with modifiers "public" 
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source) 
at java.lang.reflect.Method.invoke(Unknown Source) 

मैं बस अपना खुद का EventDispatcher वर्ग और इसके अंदर, बात यह है कि मैं प्रतिबिंब का इस्तेमाल किया है, जो भी कोड की पंक्ति है बनाने का प्रयास करते है कि का कारण बनता है समस्या है:

public void dispatchEvent(Event e, String callMethName) { 
IEventListener list = ((IEventListener)listeners[i]); 
       list.getClass().getMethod(callMethName, Event.class).invoke(list, e); 
} 

अपने मुख्य वर्ग पर, मैं कुछ है कि addListener कॉल जो सिर्फ इस तरह से EventDispatcher कक्षा में एक सूची में श्रोता जोड़ देगा है:

try { 
obj.addListener("onTestHandler", new MyTestEventListener(){ 
    @Override 
    public void onTestHandler(Event e) { 
     System.out.println("hello!"); 
    } 
}); 
} catch (SecurityException e) { 
    e.printStackTrace(); 
} 

तो पहला पैरामीटर जो "ऑनस्टेन्डलर" कहता है, EventDispatcher क्लास में और अंततः पैरामीटर कॉलमेथनाम के हिस्से के रूप में प्रेषण विधि में होगा, जो विधि को गतिशील रूप से कॉल करेगा।

विधियों का मार्ग और सबकुछ सही है। यह वह हिस्सा है जिसमें किसी भी तरह की प्रतिबिंब है। ऐसा लगता है कि विधि ढूंढने में सक्षम है। लेकिन किसी कारण से, एक अवैध एक्सेस अपवाद फेंकता है और विधि को कॉल नहीं कर सकता है।

ऐसा क्यों है?

धन्यवाद।

+1

इन सभी छोटी बिट्स को एक साथ सिलाई करने में काफी भ्रमित है। यह सब कुछ हल करने के लिए * अधिक * आसान होगा यदि आप समस्या का प्रदर्शन करने वाला एक छोटा लेकिन * पूरा * कार्यक्रम प्रदान कर सकें। यह आपके असली ऐप को करने की ज़रूरत नहीं है - इस मुद्दे को प्रदर्शित करने के लिए पर्याप्त है। –

+3

आपको अधिक जानकारी के लिए पुस्तक [जावा पज़लर] (http://www.javapuzzlers.com/) से गूढ़ व्यक्ति 'प्रतिबिंब इन्फ्लिक्शन' देखना चाहिए। वह विशिष्ट गूढ़ व्यक्ति [पुस्तक के ऑनलाइन नमूने] में उपलब्ध है (http: //www.javapuzzlers।com/जावा-पहेलियों-sampler.pdf)। –

+0

धन्यवाद रिचर्ड, नमूना अध्याय त्रुटि को समझने में बहुत मददगार है! – Carven

उत्तर

16

मुझे संदेह है कि अज्ञात वर्ग (appApp$1) जो लागू करता है MyTestEventListener में पैकेज दृश्यता है और प्रतिबिंब कोड दूसरे पैकेज में है।

इस कोड के लिए:

package foo.p1; 
public class Target { 
    public static interface Foo { 
    public void bar(); 
    } 

    public static Foo newFoo() { 
    return new Foo() { 
     @Override 
     public void bar() { 
     } 
    }; 
    } 
} 

इस कोड को विफल हो जाएगा क्योंकि क्रम newFoo() द्वारा लौटाए प्रकार एक सार्वजनिक श्रेणी नहीं है:

package foo.p2; 
import foo.p1.Target; 
public class Main { 
    public static void main(String[] args) throws Exception { 
    Target.Foo foo = Target.newFoo(); 
    foo.getClass() 
     .getMethod("bar") 
     .invoke(foo); 
    } 
} 

यह सुलभ के रूप में विधि की स्थापना करके दूर किया जा सकता:

Target.Foo foo = Target.newFoo(); 
Method m = foo.getClass() 
    .getMethod("bar"); 
m.setAccessible(true); 
m.invoke(foo); 

या सार्वजनिक इंटरफ़ेस से विधि का उपयोग करके:

Target.Foo foo = Target.newFoo(); 
Target.Foo.class.getMethod("bar") 
    .invoke(foo); 
+0

मैं इसे घंटों तक डीबग करने की कोशिश कर रहा हूं लेकिन बिना किसी किस्मत के। आपने अभी मुझे बचा लिया है !! धन्यवाद!!!! : डी – Carven

+0

सार्वजनिक इंटरफ़ेस से विधि का उपयोग करके चाल थी, धन्यवाद! – Josejulio

3

गुमनाम वर्गों तक पहुंच बहुत सीमित है .. बस list.getClass() उपयोग करने के बजाय, आप एक गैर-अनाम सुपर वर्ग या वस्तु जो विधि आप चाहते है के इंटरफेस को खोजने के लिए प्रयास करना चाहिए, और फिर आह्वान अज्ञात एक के बजाय उस कक्षा से विधि ..

मैं यह भी सुझाव दूंगा कि आप श्रोता जोड़ने और परिणाम संग्रहित करने के समय यह खोज करें। प्रतिबिंब का उपयोग करना काफी महंगा है, इसलिए सामान तेजी से चलेंगे। जितना महत्वपूर्ण हो, यदि आप विधि नाम में टाइपो बनाते हैं, तो आप उस समय त्रुटि प्राप्त करेंगे जब आप श्रोता को जोड़ते हैं, न कि भविष्य में कुछ यादृच्छिक समय पर .. इस तरह समस्या को ढूंढना बहुत आसान होगा:)

+0

बस कुछ प्रश्न, मैं गैर-कष्टप्रद सुपर क्लास या इंटरफ़ेस तक कैसे पहुंच सकता हूं? एक getParent() विधि नहीं है। इसके अलावा, आपने श्रोता जोड़ने के समय खोज करने के लिए कहा। आप किस खोज का जिक्र कर रहे हैं? धन्यवाद! – Carven

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

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