2011-12-18 18 views
5

बुला पर जावा एनोटेशन देखें चलो कहते हैं कि मैं इस तरह एक स्थिति करते हैं:विधि

public String method(String s) { 
    return stringForThisVisibility(s, EnumVisibility.PUBLIC); 
} 

और मैं इस तरह एक एनोटेशन के साथ इसे बदलना चाहते:

@VisibilityLevel(value = EnumVisibility.PUBLIC) 
public String method(String s) { 
    return stringForThisVisibility(s); 
} 

यह एक बेहतर हो रहा है और अधिक स्पष्ट समाधान है, लेकिन मुझे किसी प्रकार के प्रतिबिंब के साथ @ दृश्यता स्तर के मूल्य को जानने के लिए stringForThisVisibility विधि की आवश्यकता है। क्या यह संभव है? क्या मैं स्ट्रिंग फॉर यह दृश्यता विधि विधि पर एनोटेशन देख सकता हूं?

उत्तर

5

आपको Method ऑब्जेक्ट प्राप्त करने की आवश्यकता है जो stringForThisVisibility नामक विधि का प्रतिनिधित्व करता है। दुर्भाग्यवश, जावा बॉक्स के बाहर इस कार्यक्षमता की पेशकश नहीं करता है।

हालांकि, हम Thread.currentThread().getStackTrace() द्वारा लौटाई गई जानकारी के माध्यम से अभी भी Method प्राप्त कर सकते हैं। वह विधि StackTraceElement ऑब्जेक्ट्स की सरणी देता है।

की की: प्रत्येक StackTraceElement वस्तु हमें तीन बातें बताता है

इसमें कुछ प्रयोग हो सकते हैं, लेकिन आपको यह पता होना चाहिए कि उस सरणी में कौन सी अनुक्रमणिका आपकी रुचि रखने वाली विधि का प्रतिनिधित्व करती है (यह wil शायद सरणी में पहला, दूसरा या तीसरा StackTraceElement हो)।

एक बार जब आप वांछित है StackTraceElement, आप अपनी इसी Method वस्तु तकनीक का उपयोग कर my answer में सवाल "Get caller's method (java.lang.reflect.Method)" हकदार करने के लिए प्राप्त कर सकते हैं। वह तकनीक अभी भी शब्द होगी, भले ही कक्षा में उस विधि नाम के साथ एक से अधिक विधि हों। यदि आप उस परिदृश्य के बारे में चिंतित नहीं हैं तो सरल तकनीकें हैं।

एक बार आपके पास Method ऑब्जेक्ट हो जाने के बाद, यह method.getAnnotation(VisibilityLevel.class) पर कॉल करने का मामला है।

6

हाँ आप कर सकते थे।

StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 
Class callerClass = Class.forName(stack[stack.length-2].getClassName()); 
callerClass.isAnnotationPresent(...) 

की तर्ज पर कुछ कोड से ऊपर वर्ग पर एनोटेशन के लिए लग रहा है। आप कक्षा का नाम और विधि नाम (स्टैक ट्रेस तत्व से भी) को जोड़ सकते हैं और विधि को देख सकते हैं। ध्यान दें कि यह बेहद धीमा है।

+2

मुझे पता है कि एकमात्र समाधान भी है। यह नहीं कि सभी परिस्थितियों में काम करने की गारंटी नहीं है: यदि क्लासलोडर जिसे कॉल किया गया क्लास लोड किया जाता है, उसे कॉलिंग क्लास (और उसके माता-पिता क्लासलोडर्स में से कोई भी नहीं) पता नहीं है, तो 'class.forName() 'पर कॉल विफल हो जाएगा। –

+0

तो आप कहते हैं कि पहले समाधान से संतुष्ट होना बेहतर होगा ... – Fabio

+1

यह तकनीक नाजुक है (क्या होगा यदि आपकी विधि को एनोटेटेड विधि से सीधे नहीं कहा गया था? आपको स्टैक के माध्यम से लूप करना होगा। अगर एनोटेशन एक सुपरक्लास विधि पर है और सीधे कॉलिंग विधि पर नहीं है? आपको सुपरक्लास पर लूप करना होगा ...) और यदि फिलिप सही है तो यह जटिल वातावरण (j2ee? osgi?) के लिए खराब हो सकता है। यह भी बहुत धीमी है। आप एक समाधान का चयन कर सकते हैं जो थ्रेडलोकल मार्कर का उपयोग करता है और विधि को कॉल करने से पहले मार्कर सेट करता है, लेकिन यह अजीब भी दिखाई देगा। हो सकता है कि आप वर्णन कर सकें कि आप वास्तव में एक सुरुचिपूर्ण समाधान करने की कोशिश कर रहे हैं – radai

8
निम्नलिखित वर्ग के साथ

:

/** 
    * Proper use of this class is 
    *  String testName = (new Util.MethodNameHelper(){}).getName(); 
    * or 
    *  Method me = (new Util.MethodNameHelper(){}).getMethod(); 
    * the anonymous class allows easy access to the method name of the enclosing scope. 
    */ 
    public static class MethodNameHelper { 
    public String getName() { 
     final Method myMethod = this.getClass().getEnclosingMethod(); 
     if (null == myMethod) { 
     // This happens when we are non-anonymously instantiated 
     return this.getClass().getSimpleName() + ".unknown()"; // return a less useful string 
     } 
     final String className = myMethod.getDeclaringClass().getSimpleName(); 
     return className + "." + myMethod.getName() + "()"; 
    } 

    public Method getMethod() { 
     return this.getClass().getEnclosingMethod(); 
    } 
    } 

एक कॉल कर सकते हैं:। विधि मुझे = (नई Util.MethodNameHelper() {}) getMethod();

मैं उस कक्षा में getName() कॉल का व्यापक उपयोग करता हूं। मेरी मशीन पर उन अज्ञात वर्ग तात्कालिकताओं के साथ विधि चालान प्रत्येक के बारे में 1500 एनएस खर्च करते हैं। स्टैकएलेमेंट पैदल दृष्टिकोण मेरे प्रदर्शन परीक्षण में मेरी मशीन पर लगभग 30 गुना (47000 एनएस) खर्च करता है।

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