2012-05-29 18 views
12

बाहरी कक्षा से गुमनाम आंतरिक कक्षाओं के भीतर परिभाषित नई विधियों तक पहुंचने के लिए कोई जावा वाक्यविन्यास है? मुझे पता है कि विभिन्न कामकाज हो सकते हैं, लेकिन मुझे आश्चर्य है कि एक विशेष वाक्यविन्यास मौजूद है या नहीं?क्या मैं कुछ वाक्यविन्यास के साथ अनाम आंतरिक कक्षा में नए तरीकों तक पहुंच सकता हूं?

उदाहरण

class Outer { 

    ActionListener listener = new ActionListener() { 

     @Override 
     void actionPerformed(ActionEvent e) { 
      // do something 
     } 

     // method is public so can be accessible 
     public void MyGloriousMethod() { 
      // viva! 
     } 

    }; 

    public void Caller() { 
     listener.MyGloriousMethod(); // does not work! 
    } 


} 

मेरी स्वयं समाधान

के लिए मैं सिर्फ बाहरी कक्षा तक के सभी तरीकों और सदस्यों ले जाया गया।

उत्तर

18

एक बार अज्ञात वर्ग के उदाहरण को नामित प्रकार में डाला गया है, इसे वापस नहीं किया जा सकता क्योंकि अनाम प्रकार के लिए कोई नाम नहीं है। कक्षा के भीतर this के माध्यम से अज्ञात आंतरिक कक्षा के अतिरिक्त सदस्यों तक पहुंच सकते हैं, अभिव्यक्ति के तुरंत बाद अभिव्यक्ति में और प्रकार का अनुमान लगाया जा सकता है और विधि कॉल के माध्यम से वापस किया जा सकता है।

Object obj = new Object() { 
    void fn() { 
     System.err.println("fn"); 
    } 
    @Override public String toString() { 
     fn(); 
     return ""; 
    } 
}; 
obj.toString(); 



new Object() { 
    void fn() { 
     System.err.println("fn"); 
    } 
}.fn(); 


identity(new Object() { 
    void fn() { 
     System.err.println("fn"); 
    } 
}).fn(); 
... 
private static <T> T identity(T value) { 
    return value; 
} 
+0

वाह! आप उस मामले को जानते हैं जब अज्ञात वर्ग के सदस्य को बुलाया जा सकता है! –

3

आपका कॉलर listener को ActionListener के रूप में जानता है और इसलिए यह उस नई विधि के बारे में कुछ भी नहीं जानता है। मुझे लगता है कि ऐसा करने का एकमात्र तरीका (प्रतिबिंब जिम्नास्टिक करने के अलावा, जो वास्तव में एक अज्ञात वर्ग का उपयोग करने के उद्देश्य को हरा देगा, यानी शॉर्टकट/सादगी) ActionListener को उप-वर्ग करना है और अज्ञात वर्ग का उपयोग नहीं करना है।

+0

हाँ। यहां समाधान है ... इसे अनाम मत बनाओ। –

+0

@ लुइस अगर मैं इसे अनाम नहीं करता हूं तो मुझे सिंटैक्स अर्थव्यवस्था से लाभ नहीं होगा। मुझे एक वर्ग और इसका एक उदाहरण बनाने की आवश्यकता होगी। –

+0

@ सुज़ानसिओक: आप वर्तमान कोड के साथ एक वर्ग और इसका एक उदाहरण भी बनाते हैं। कक्षा अज्ञात है, लेकिन यह एकमात्र अंतर है। –

1

नहीं, यह असंभव है। आपको एक्शनलिस्टर को अपने असली उप-वर्ग नाम पर डालना होगा, लेकिन चूंकि यह अनाम है, इसका नाम नहीं है।

+0

लेकिन वे इसके लिए कुछ कीवर्ड बना सकते हैं जैसे 'listener.that.MyGloriousMethod() 'या' ((बेनामी) श्रोता) .MyGloriousMethod() 'चूंकि अज्ञात वर्ग वास्तव में JVM के लिए अज्ञात नहीं है लेकिन केवल यह नाम प्रोग्रामर के लिए अज्ञात है और इसलिए समस्या किसी भी तरह इसे इंगित करने के लिए है। –

+0

वे कुछ कल्पना कर सकते थे, लेकिन उन्होंने नहीं किया, क्योंकि यह पहले से ही बहुत ही आसान है: गैर-अज्ञात आंतरिक वर्ग बनाकर। –

1

यह करने के लिए सही तरीके से प्रतिबिंब का उपयोग किया जाता है:

import java.lang.reflect.InvocationTargetException; 

public class MethodByReflectionTest { 

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { 

     Object obj = new Object(){ 
      public void print(){ 
       System.out.println("Print executed."); 
      } 
     }; 

     obj.getClass().getMethod("print", null).invoke(obj, null); 
    } 
} 

आप यहाँ देख सकते हैं: How do I invoke a Java method when given the method name as a string?

5

मेरी कक्षा में एक छात्र हमारे प्रोफेसर से पूछा कि क्या यह दूसरे दिन किया जा सकता है ।

public static void main(String[] args){ 

    //anonymous inner class with method defined inside which 
    //does not override anything 
    Object o = new Object() 
    { 
     public int test = 5; 
     public void sayHello() 
     { 
      System.out.println("Hello World"); 
     } 
    }; 

    //o.sayHello();//Does not work 

    try 
    { 
     Method m = o.getClass().getMethod("sayHello"); 
     Field f = o.getClass().getField("test"); 
     System.out.println(f.getInt(o)); 
     m.invoke(o); 
    } catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

जावा के विधि वर्ग का इस्तेमाल कर रही करके हम एक विधि आह्वान कर सकते हैं: यहाँ है कि मैं क्या अवधारणा के एक शांत सबूत है कि ऐसा किया जा सकता के रूप में लिखा है, हालांकि नहीं इसके लायक, यह वास्तव में संभव है और यहाँ कैसे किया जाता है विधि के स्ट्रिंग मान और पैरामीटर में गुजरकर। खेतों के साथ वही काम किया जा सकता है।

बस सोचा कि यह साझा करने के लिए अच्छा होगा!

0

हाँ, आप उपयोग कर सकते हैं विधि नीचे उदाहरण देखें, तो कोई संदेह टिप्पणी कृपया

package com; 
interface A 
{ 
    public void display(); 
} 
public class Outer { 
    public static void main(String []args) 
    { 
     A a=new A() { 
     @Override 
     public void display() { 
      System.out.println("Hello"); 
     } 
    }; 
     a.display(); 
    } 
    }