2009-12-07 16 views
23

के माध्यम से किसी दिए गए वर्ग के लिए सुलभ विधियों की एक सूची प्राप्त करना क्या किसी दिए गए वर्ग द्वारा सुलभ (आवश्यक रूप से सार्वजनिक नहीं) विधियों की एक सूची प्राप्त करने का कोई तरीका है? प्रश्न में कोड पूरी तरह से अलग वर्ग में होगा।प्रतिबिंब

उदाहरण:

public class A { 
    public void methodA1(); 
    protected void methodA2(); 
    void methodA3(); 
    private void methodA4(); 
} 

public class B extends A { 
    public void methodB1(); 
    protected void methodB2(); 
    private void methodB3(); 
} 

वर्ग B के लिए मैं चाहता हूँ प्राप्त करने के लिए:

  • अपने स्वयं के तरीकों
  • methodA1 और methodA2 वर्ग से के सभी A
  • methodA3 तभी यदि कक्षा B उसी पैकेज में है A

methodA4 परिणामों में कभी भी शामिल नहीं होना चाहिए क्योंकि यह B वर्ग के लिए पहुंच योग्य नहीं है। एक बार फिर से स्पष्टीकरण के लिए, उपरोक्त विधियों को खोजने और वापस करने के लिए आवश्यक कोड पूरी तरह से अलग वर्ग/पैकेज में होंगे।

अब, Class.getMethods() केवल सार्वजनिक तरीकों को लौटाता है और इस प्रकार मैं जो चाहता हूं वह नहीं करेगा; Class.getDeclaredMethods() केवल वर्तमान कक्षा के लिए विधियों को लौटाता है। जबकि मैं निश्चित रूप से उत्तरार्द्ध का उपयोग कर सकता हूं और कक्षा पदानुक्रम को दृश्यता नियमों को मैन्युअल रूप से जांचने के लिए चला सकता हूं, लेकिन अगर बेहतर समाधान हो तो मैं नहीं चाहूंगा। क्या मैं यहां कुछ चमकदार रूप से स्पष्ट हूं?

उत्तर

29

कक्षा या इंटरफ़ेस से सभी विधियों (निजी या अन्यथा) की सूची प्राप्त करने के लिए Class.getDeclaredMethods() का उपयोग करें।

Class c = ob.getClass(); 
for (Method method : c.getDeclaredMethods()) { 
    if (method.getAnnotation(PostConstruct.class) != null) { 
    System.out.println(method.getName()); 
    } 
} 

नोट: इस विरासत में मिला तरीकों शामिल नहीं है। इसके लिए Class.getMethods() का उपयोग करें। यह सभी सार्वजनिक विधियों (विरासत में या नहीं) वापस कर देगा।

किसी वर्ग की पहुंच (विरासत विधियों समेत) की एक विस्तृत सूची करने के लिए, आपको कक्षाओं के वृक्ष को पार करने की आवश्यकता होगी। तो:

Class c = ob.getClass(); 
for (Class c = ob.getClass(); c != null; c = c.getSuperclass()) { 
    for (Method method : c.getDeclaredMethods()) { 
    if (method.getAnnotation(PostConstruct.class) != null) { 
     System.out.println(c.getName() + "." + method.getName()); 
    } 
    } 
} 
+1

कि अभी भी जो मैं चाहता क्योंकि यह निजी/पैकेज निजी तरीके के रूप में अच्छी तरह से वापस आ जाएगी ऐसा नहीं करता है: तो मेरे लिए पूरा कोड (इनपुट तर्क प्रकारों, संशोधक और प्रकार वापसी सहित) था। एनोटेटेड विधियों को खोजने के लिए आपका कोड पूरी तरह से उचित है; मुझे जो चाहिए वह रन टाइम पर पता लगाने के लिए है कि 'बी' इंस्टेंस का उपयोग किया जा सकता है। जैसा कि मैंने कहा, मैं ऐसा करने के लिए कोड लिख सकता हूं (आपके द्वारा पोस्ट की गई चीज़ों के समान और एक्सेसिबिलिटी की जांच करने के लिए फेंकने वाले कुछ ifs) लेकिन मैं सोच रहा था कि कोई बेहतर तरीका है या नहीं। – ChssPly76

+0

अच्छी तरह से ऐसा करने के लिए कोई मानक एपीआई फ़ंक्शन नहीं है ताकि आप इसे स्वयं लिख रहे हों। बस। आप कुछ हद तक असामान्य आवश्यकता कर रहे हैं। आम तौर पर प्रतिबिंब के साथ आप केवल सार्वजनिक रूप से ** पहुंच योग्य होते हैं, इसलिए getMethods() और यही कारण है कि सहायक कार्य मौजूद है। आप जो चाहते हैं उसके लिए ऐसा कोई भी मानक (मानक) सहायक नहीं है इसलिए आप इसे स्वयं लिख रहे हैं। – cletus

+0

मुझे पता है कि कोई मानक एपीआई नहीं है; मैं उम्मीद कर रहा था कि किसी को भी ऐसी ही समस्या हो और समाधान मिले - लेकिन मुझे नहीं लगता। मैंने बीन्यूटिल्स/जावसिस्ट/आदि जैसे स्पष्ट स्थानों में इससे संबंधित कुछ भी नहीं देखा ... या तो। संहिता कुछ हद तक शामिल हो गई, असल में - नेस्टेड कक्षाओं में सिंथेटिक तरीकों से निपटने के लिए ... – ChssPly76

2

सुनिश्चित करें कि आपको जो चाहिए वो प्राप्त करने के लिए आपको सुपरक्लास को चलना होगा। आखिरकार, getMethods() getDeclaredMethods() आंतरिक रूप से कॉल के साथ कर रहा है (प्रकार: यह वास्तव में एक निजी संस्करण कहता है जो गैर-सार्वजनिक तरीकों को फ़िल्टर करता है लेकिन यह पूरी सूची बनाने के लिए कक्षा के पेड़ को पार करता है)।

उत्सुक क्यों ऐसी चीज की आवश्यकता है, हालांकि।

5

चूंकि क्लीटस और पीएसपीड ने पहले से ही उत्तर दिया है - आपको कक्षाओं के विरासत के पेड़ को पार करने की आवश्यकता है।

इस तरह से मैं यह करना है, लेकिन पैकेज निजी तरीकों से निपटने के बिना:

public static Method[] getAccessibleMethods(Class clazz) { 
    List<Method> result = new ArrayList<Method>(); 

    while (clazz != null) { 
     for (Method method : clazz.getDeclaredMethods()) { 
     int modifiers = method.getModifiers(); 
     if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) { 
      result.add(method); 
     } 
     } 
     clazz = clazz.getSuperclass(); 
    } 

    return result.toArray(new Method[result.size()]); 
} 

मैं एक पीछे की ओर-संगतता चेकर में यह उपयोग कर रहा हूँ मैं कहाँ पता है कि कक्षाओं कि प्रभावित हो सकता है में नहीं होगा वही पैकेज वैसे भी।

0

कैलेटस के उत्तर पर एक बिंदु (मैं वहां टिप्पणी नहीं कर सकता क्योंकि मेरे पास पर्याप्त प्रतिष्ठा नहीं है।)।वैसे भी, कि्लिटस के कोड मेरे लिए काम नहीं किया 2009

लाइन के बाद से शायद जावा में परिवर्तन के कारण (ग्रहण भी इसके बारे में शिकायत करते हुए),:

:

for (Class c = ob.getClass(); c != null; c = c.getSuperclass()) { 

था परिवर्तित करने

for (Class<?> c = ob.getClass(); c != null; c = c.getSuperclass()) { 

कोई भी आउटपुट प्राप्त करने के लिए।

for (Class<?> c = scanner.getClass(); c != null; c = c.getSuperclass()) { 
     System.out.println(c.getName());   
     for (Method method : c.getMethods()) { 
      System.out.println("\t" + Modifier.toString(method.getModifiers()) 
      + " " + method.getName()); 
      for (Class<?> param: method.getParameterTypes()) { 
       System.out.println("\t\t" + param.getName()); 
      } 
      System.out.println("\t\t == returns ==> " + method.getReturnType().getName()); 
     } 
    }