वर्तमान में निष्पादित विधि का नाम प्राप्त करना


जवाबों:


177

Thread.currentThread().getStackTrace()आमतौर पर उस विधि को शामिल करेंगे जिसे आप इसे कॉल कर रहे हैं लेकिन इसमें कुछ नुकसान हैं (देखें Javadoc ):

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


7
क्या अपवादों में ढेर के निशान के लिए यह वही नुकसान है?
नैट पार्सन्स

8
हाँ यही है। के लिए दस्तावेज़ फेंकने योग्य । [GetStackTrace ()] ( download.oracle.com/javase/1.5.0/docs/api/java/lang/... ठीक उसी पैराग्राफ में शामिल है।
Bombe

4
अंतर्निहित बात यह है कि जेवीएम को स्टैकट्रेस प्रदान करने में सक्षम होने की आवश्यकता नहीं है , लेकिन यह कि बहुत सारे काम हॉटस्पॉट को बहुत विश्वसनीय बनाने में चले गए हैं। हालांकि, आपको यह जानना होगा कि यदि आप चाहते हैं कि आपका कोड किसी विशिष्ट JVM के व्यवहार पर निर्भर न हो।
थोरबजोरन राव एंडरसन

नीचे एलेक्स्समेल का संस्करण स्टैक ट्रेस नहीं बनाता है और आपको वास्तविक विधि ऑब्जेक्ट तक पहुंच प्रदान करता है, न कि केवल नाम (ताकि आप रिटर्न प्रकार भी पा सकें)। मैंने बेंच मार्क नहीं किया है, लेकिन मुझे संदेह है कि उसका तरीका बहुत तेज़ है क्योंकि स्टैक के निशान महंगे हैं।
गस

डेविन की प्रतिक्रिया इस प्रश्न का अधिक संक्षिप्त उत्तर देती है।
उदय

310

तकनीकी रूप से यह काम करेगा ...

String name = new Object(){}.getClass().getEnclosingMethod().getName();

हालाँकि, संकलन समय (जैसे YourClass$1.class) के दौरान एक नया अनाम आंतरिक वर्ग बनाया जाएगा । तो यह .classप्रत्येक विधि के लिए एक फाइल बनाएगा जो इस ट्रिक को दर्शाती है। इसके अतिरिक्त रनटाइम के दौरान प्रत्येक इनवोकेशन पर अन्यथा अप्रयुक्त ऑब्जेक्ट इंस्टेंस बनाया जाता है। तो यह एक स्वीकार्य डिबग ट्रिक हो सकता है, लेकिन यह महत्वपूर्ण ओवरहेड के साथ आता है।

इस ट्रिक का एक फायदा यह है कि एनोटेशन और पैरामीटर नाम सहित विधि की अन्य सभी जानकारी प्राप्त करने के लिए getEncosingMethod()रिटर्न का java.lang.reflect.Methodउपयोग किया जा सकता है। यह एक ही नाम (विधि अधिभार) के साथ विशिष्ट तरीकों के बीच अंतर करना संभव बनाता है।

ध्यान दें कि getEnclosingMethod()इस ट्रिक के JavaDoc के अनुसार नहीं फेंकना चाहिए क्योंकि एक SecurityExceptionही वर्ग लोडर का उपयोग करके आंतरिक कक्षाओं को लोड किया जाना चाहिए। इसलिए सुरक्षा प्रबंधक मौजूद होने पर भी एक्सेस शर्तों की जांच करने की आवश्यकता नहीं है।

getEnclosingConstructor()निर्माणकर्ताओं के लिए इसका उपयोग करना आवश्यक है । (नामित) विधियों के बाहर ब्लॉक के दौरान, getEnclosingMethod()रिटर्न null


9
यह आपको वर्तमान में निष्पादन विधि नहीं देगा। यह आपको वह विधि देगा जिसमें एक अनाम / स्थानीय वर्ग परिभाषित किया गया है। - docs.oracle.com/javase/6/docs/api/java/lang/…
shrini1000

7
वर्ग स्थानीय {}; स्ट्रिंग नाम = Local.class.getEnclosingMethod ()। GetName ();
एलेक्समेल

21
@ shrini1000 इस विचार का उपयोग इस स्निपेट का उपयोग करना है जहां जानकारी की आवश्यकता है, और इसे पुस्तकालय की दिनचर्या में न डालें।
थोरबजोरन राव एंडरसन

4
सुझावों के लिए धन्यवाद! एक नई वस्तु बनाने के बजाय, बस इस का उपयोग करें ।getClass ()। GetEnclosingMethod ()। GetName ();
लीलो

3
@ लिलो गलत। getEnclosingMethodउस पद्धति का नाम मिलता है जहाँ कक्षा को परिभाषित किया गया है। this.getClass()तुम सब में मदद नहीं करेगा। @wutzebaer आपको भी इसकी आवश्यकता क्यों होगी? आपके पास उनकी पहुंच पहले से है।
हेज़ल ट्रॉस्ट

134

जनवरी 2009:
एक पूर्ण कोड होगा ( @ बॉम्बे के कैविट को ध्यान में रखकर):

/**
 * Get the method name for a depth in call stack. <br />
 * Utility function
 * @param depth depth in the call stack (0 means current method, 1 means call method, ...)
 * @return method name
 */
public static String getMethodName(final int depth)
{
  final StackTraceElement[] ste = Thread.currentThread().getStackTrace();

  //System. out.println(ste[ste.length-depth].getClassName()+"#"+ste[ste.length-depth].getMethodName());
  // return ste[ste.length - depth].getMethodName();  //Wrong, fails for depth = 0
  return ste[ste.length - 1 - depth].getMethodName(); //Thank you Tom Tresansky
}

में अधिक इस सवाल का

अद्यतन दिसंबर 2011:

स्पष्ट टिप्पणियां:

मैं JRE 6 का उपयोग करता हूं और मुझे गलत विधि का नाम देता है।
अगर मैं लिखता हूं तो यह काम करता हैste[2 + depth].getMethodName().

  • 0है getStackTrace(),
  • 1है getMethodName(int depth)और
  • 2 विधि है।

virgo47 का उत्तर ( उत्कीर्णित ) वास्तव में विधि के नाम को वापस पाने के लिए लागू करने के लिए सही सूचकांक की गणना करता है।


2
यह केवल मेरे लिए "मुख्य" कहता है। : - /
प्रो। फॉकन अनुबंध

@ योग्य: क्या आपने StackTraceElementडिबगिंग उद्देश्य के लिए सभी सरणी को प्रिंट करने की कोशिश की और यह देखने के लिए कि क्या 'मुख्य' वास्तव में सही तरीका है?
वॉन

7
मैं JRE 6 का उपयोग करता हूं और मुझे गलत विधि का नाम देता है। अगर मैं लिखता हूं तो यह काम करता है ste[2 + depth].getMethodName()। 0 है getStackTrace(), 1 है getMethodName(int depth)और 2 है। आप भी देखिए @ virgo47 का जवाब
नीले रंग का

2
@ बबलिश: अच्छी बात है। मैंने आपकी टिप्पणी और virgo47 के जवाब को खान में शामिल किया है।
वॉन

@VonC क्या यह कार्यान्वयन वास्तव में सही है? वर्तमान विधि देने के लिए यहाँ गहराई ste.length + 1 होनी चाहिए। अगर हमें गहराई = 0 की अनुमति दी जाए तो क्या यह कदम [गहराई + 1] नहीं होना चाहिए?
mmm

85

हमने स्टैक ट्रेस इंडेक्स में संभावित परिवर्तनशीलता को कम करने के लिए इस कोड का उपयोग किया है - अब बस मेथडनाम का उपयोग करें:

public class MethodNameTest {
    private static final int CLIENT_CODE_STACK_INDEX;

    static {
        // Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
        int i = 0;
        for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
            i++;
            if (ste.getClassName().equals(MethodNameTest.class.getName())) {
                break;
            }
        }
        CLIENT_CODE_STACK_INDEX = i;
    }

    public static void main(String[] args) {
        System.out.println("methodName() = " + methodName());
        System.out.println("CLIENT_CODE_STACK_INDEX = " + CLIENT_CODE_STACK_INDEX);
    }

    public static String methodName() {
        return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX].getMethodName();
    }
}

लगता है, लेकिन हमारे पास JDK 1.5 के लिए कुछ निश्चित संख्या थी और जब हम JKK 1.6 में चले गए, तो थोड़ा आश्चर्यचकित थे। अब जावा 6/7 में भी ऐसा ही है, लेकिन आप कभी नहीं जानते। यह रनटाइम के दौरान उस इंडेक्स में बदलाव का सबूत नहीं है - लेकिन उम्मीद है कि हॉटस्पॉट उस बुरे को नहीं करेगा। :-)


1
यह अभी भी सूक्ष्म रूप से विक्रेता पर निर्भर है। इस कोड के लिए विश्वसनीय डेटा देने के लिए JVM की आवश्यकता नहीं है।
थोरबजोरन रावन एंडरसन

6
JVM कल्पना के अनुसार JVM को पूर्ण स्टैक ट्रैस प्रदान करने की आवश्यकता नहीं है (अनुकूलन, इनलाइनिंग और वह सब) और आपने पहले ही पता लगा लिया है कि ओरेकल जावा 5 और ओरेकल जावा 6 के बीच आपका अनुमानी बदल गया है। इस बात की कोई गारंटी नहीं है कि कोई अन्य वीवीएम होगा अपने कोड में अपेक्षा के अनुसार व्यवहार करें, इसलिए आप विक्रेता विशिष्ट व्यवहार पर सूक्ष्मता से भरोसा कर रहे हैं। जो पूरी तरह से ठीक है, जब तक कि आप इसके बारे में जानते हैं, लेकिन अगर - उदाहरण के लिए - आपको एक आईबीएम जेवीएम (जिसे हमें चाहिए) या एक ज़िंग उदाहरण पर तैनात करने की आवश्यकता है, तो आपको अपने उत्तराधिकार को फिर से देखना होगा।
Thorbjørn रेवन एंडरसन

1
यह यहां प्रस्तुत सभी विकल्पों में से सबसे मजबूत लगता है, निर्भरता के बावजूद।
इयान

46
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

नाम का मूल्य फू होगा।


5
स्थानीय .class.getEnclosingMethod () शून्य था। jdk1.6.0_31,
ईजी

@ विजिल दिलचस्प है लेकिन अधिक जानकारी के बिना यह बताना मुश्किल है कि "गलत" क्या हुआ या जब हमें उम्मीद करनी चाहिएnull
Maarten Bodewes

यह उत्तर के रूप में एक ही चाल है । इसका यह फायदा है कि यह एक सहज वस्तु उदाहरण नहीं बनाता है, इसका नुकसान यह है कि इसके लिए एक वर्ग की घोषणा की आवश्यकता होती है जिसे बयान में इनबिल्ट नहीं किया जा सकता है (अर्थात आमतौर पर इसके लिए अतिरिक्त लाइन की आवश्यकता होती है)।
मार्टन बोडेवेस

@eigil ने आपको कक्षा के भीतर (उदाहरण SomeClass), या एक विधि (उदाहरण foo) के भीतर परिभाषित किया था? मैंने पाया कि एक उप-आवरण को एक विधि में लपेटे बिना परिभाषित किया जा रहा है - या एक कंस्ट्रक्टर में - null वापस करने के लिए getEnclosingMethod () का कारण होगा।
DN

बहुत यकीन है कि मैं इस जवाब में वर्णित के रूप में किया था। मुझे लगता है कि यह playframework के साथ कुछ अजीब है। बिना किसी समस्या के 'सामान्य' जावा में परीक्षण किया गया।
ईगली

36

ये दोनों विकल्प मेरे लिए जावा के साथ काम करते हैं:

new Object(){}.getClass().getEnclosingMethod().getName()

या:

Thread.currentThread().getStackTrace()[1].getMethodName()

1
स्थैतिक तरीकों का उपयोग करने के लिए: <क्लास> .class.getEnclosingMethod ()। getName ()
jellobird

बॉम्बे के उत्तर और जेवाडॉक संकेत के अनुसार खाली सरणी का ध्यान रखें। कुछ JVM स्टैकट्रेस सरणी नहीं भर सकते हैं?
एल-टेदी

34

सबसे तेज़ तरीका मैंने पाया है कि:

import java.lang.reflect.Method;

public class TraceHelper {
    // save it static to have it available on every call
    private static Method m;

    static {
        try {
            m = Throwable.class.getDeclaredMethod("getStackTraceElement",
                    int.class);
            m.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getMethodName(final int depth) {
        try {
            StackTraceElement element = (StackTraceElement) m.invoke(
                    new Throwable(), depth + 1);
            return element.getMethodName();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

यह मूल विधि getStackTraceElement (int गहराई) को सीधे एक्सेस करता है। और एक स्थिर चर में सुलभ विधि को संग्रहीत करता है।


3
प्रदर्शन के लिहाज से सबसे तेज? दावे का समर्थन करने के लिए कोई सूक्ष्म बेंचमार्क?
इब्राहिम दुख

10
+1। 1.6 पर एक साधारण समयबद्ध लूप का उपयोग करते हुए, इस विधि का उपयोग करते हुए 1,000,000 पुनरावृत्तियों ने 1219ms लिया, जबकि new Throwable().getStackTrace()5614ms का उपयोग किया ।
ACH

1
m.setAccessible (सही); AccessController.doPrivileged से घिरा होना चाहिए। कुछ विचार करने के लिए, एक कठिन नियम नहीं जो मैं कहूंगा
23:14

6
2016 में परीक्षण किया गया और यह सबसे तेज जारी है। @Ach की तरह मैंने 1M पुनरावृत्तियों का उपयोग किया। 1.7_79: 1.6s बनाम 15.2s 1.8_74: 1.8s बनाम 16.0s। FWIW मेरे बेंचमार्क स्टेप ऐरे की लंबाई == 23 है, लेकिन स्टैक डेप्थ की परवाह किए बिना यह विधि तेज रहती है।
रयान

25

निम्नलिखित कोड का उपयोग करें:

    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
    StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
    String methodName = e.getMethodName();
    System.out.println(methodName);

2
यह मेरे लिए "getStackTrace" को प्रिंट करता है - मैं जावा 1.5 का उपयोग कर रहा हूं
Zack Macomber

बॉम्बे के उत्तर और जेवाडॉक संकेत के अनुसार खाली सरणी का ध्यान रखें। कुछ JVM स्टैकट्रेस सरणी नहीं भर सकते हैं?
एल-टेदी

16
public static String getCurrentMethodName() {
        return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
    }

हां, अब तक का सबसे अच्छा ... इसे एक विधि में बदल दें और ट्रेस में तीसरा ([2]) फ्रेम (या इसे जो भी कहा जाए) प्राप्त करें।
माइक कृंतक

14

यह virgo47 के उत्तर (ऊपर) पर एक विस्तार है ।

यह वर्तमान और इनवॉइसिंग क्लास / मेथड नाम प्राप्त करने के लिए कुछ स्थैतिक विधियाँ प्रदान करता है।

/* Utility class: Getting the name of the current executing method 
 * /programming/442747/getting-the-name-of-the-current-executing-method
 * 
 * Provides: 
 * 
 *      getCurrentClassName()
 *      getCurrentMethodName()
 *      getCurrentFileName()
 * 
 *      getInvokingClassName()
 *      getInvokingMethodName()
 *      getInvokingFileName()
 *
 * Nb. Using StackTrace's to get this info is expensive. There are more optimised ways to obtain
 * method names. See other stackoverflow posts eg. /programming/421280/in-java-how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection/2924426#2924426
 *
 * 29/09/2012 (lem) - added methods to return (1) fully qualified names and (2) invoking class/method names
 */
package com.stackoverflow.util;

public class StackTraceInfo
{
    /* (Lifted from virgo47's stackoverflow answer) */
    private static final int CLIENT_CODE_STACK_INDEX;

    static {
        // Finds out the index of "this code" in the returned stack trace - funny but it differs in JDK 1.5 and 1.6
        int i = 0;
        for (StackTraceElement ste: Thread.currentThread().getStackTrace())
        {
            i++;
            if (ste.getClassName().equals(StackTraceInfo.class.getName()))
            {
                break;
            }
        }
        CLIENT_CODE_STACK_INDEX = i;
    }

    public static String getCurrentMethodName()
    {
        return getCurrentMethodName(1);     // making additional overloaded method call requires +1 offset
    }

    private static String getCurrentMethodName(int offset)
    {
        return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getMethodName();
    }

    public static String getCurrentClassName()
    {
        return getCurrentClassName(1);      // making additional overloaded method call requires +1 offset
    }

    private static String getCurrentClassName(int offset)
    {
    return Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getClassName();
    }

    public static String getCurrentFileName()
    {
        return getCurrentFileName(1);     // making additional overloaded method call requires +1 offset
    }

    private static String getCurrentFileName(int offset)
    {
        String filename = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getFileName();
        int lineNumber = Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX + offset].getLineNumber();

        return filename + ":" + lineNumber;
    }

    public static String getInvokingMethodName()
    {
        return getInvokingMethodName(2); 
    }

    private static String getInvokingMethodName(int offset)
    {
        return getCurrentMethodName(offset + 1);    // re-uses getCurrentMethodName() with desired index
    }

    public static String getInvokingClassName()
    {
        return getInvokingClassName(2); 
    }

    private static String getInvokingClassName(int offset)
    {
        return getCurrentClassName(offset + 1);     // re-uses getCurrentClassName() with desired index
    }

    public static String getInvokingFileName()
    {
        return getInvokingFileName(2); 
    }

    private static String getInvokingFileName(int offset)
    {
        return getCurrentFileName(offset + 1);     // re-uses getCurrentFileName() with desired index
    }

    public static String getCurrentMethodNameFqn()
    {
        return getCurrentMethodNameFqn(1);
    }

    private static String getCurrentMethodNameFqn(int offset)
    {
        String currentClassName = getCurrentClassName(offset + 1);
        String currentMethodName = getCurrentMethodName(offset + 1);

        return currentClassName + "." + currentMethodName ;
    }

    public static String getCurrentFileNameFqn()
    {
        String CurrentMethodNameFqn = getCurrentMethodNameFqn(1);
        String currentFileName = getCurrentFileName(1);

        return CurrentMethodNameFqn + "(" + currentFileName + ")";
    }

    public static String getInvokingMethodNameFqn()
    {
        return getInvokingMethodNameFqn(2);
    }

    private static String getInvokingMethodNameFqn(int offset)
    {
        String invokingClassName = getInvokingClassName(offset + 1);
        String invokingMethodName = getInvokingMethodName(offset + 1);

        return invokingClassName + "." + invokingMethodName;
    }

    public static String getInvokingFileNameFqn()
    {
        String invokingMethodNameFqn = getInvokingMethodNameFqn(2);
        String invokingFileName = getInvokingFileName(2);

        return invokingMethodNameFqn + "(" + invokingFileName + ")";
    }
}

3
@ Mklemenz के उत्तर के साथ यह स्टैक जानकारी तक पहुँचने का एक बहुत तेज़ और साफ तरीका है।
ओक्टाविया तोगामी

12

उस विधि का नाम प्राप्त करने के लिए जिसे आप वर्तमान विधि कह सकते हैं:

new Exception("is not thrown").getStackTrace()[1].getMethodName()

यह मेरे मैकबुक के साथ-साथ मेरे एंड्रॉइड फोन पर भी काम करता है

मैंने भी कोशिश की:

Thread.currentThread().getStackTrace()[1]

लेकिन एंड्रॉइड "getStackTrace" वापस कर देगा मैं इसे एंड्रॉइड के लिए ठीक कर सकता हूं

Thread.currentThread().getStackTrace()[2]

लेकिन फिर मुझे अपने मैकबुक पर गलत जवाब मिलता है


हाल ही में एंड्रॉइड पर परीक्षण में, इसके getStackTrace()[0]बजाय मेरे लिए उपयोग करना बेहतर था getStackTrace()[1]। YMMV।
mbm29414

Android के लिए ऊपर हैThread.currentThread().getStackTrace()[2]
निंजा

11

Util.java:

public static String getCurrentClassAndMethodNames() {
    final StackTraceElement e = Thread.currentThread().getStackTrace()[2];
    final String s = e.getClassName();
    return s.substring(s.lastIndexOf('.') + 1, s.length()) + "." + e.getMethodName();
}

SomeClass.java:

public class SomeClass {
    public static void main(String[] args) {
        System.out.println(Util.getCurrentClassAndMethodNames()); // output: SomeClass.main
    }
}

final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; काम करता है; e.getClassName();पूरी कक्षा का नाम e.getMethodName()वापस करें और मेथॉन नाम वापस करें।
मार्क्स

1
getStackTrace()[2]यह गलत है, getStackTrace()[3]क्योंकि ऐसा होना चाहिए : [०] dalvik.system.VMStack.getThreadStackTrace [१] java.lang.Thread.getStackTrace [२] यूटिल्स.गैलेटरीक्लास क्लाडएंडमैथोडनाम्स [३] फ़ंक्शन इस (कॉलिंग) को एक
PhilLab

11

यह StackWalkerजावा 9 के बाद से किया जा सकता है ।

public static String getCurrentMethodName() {
    return StackWalker.getInstance()
                      .walk(s -> s.skip(1).findFirst())
                      .get()
                      .getMethodName();
}

public static String getCallerMethodName() {
    return StackWalker.getInstance()
                      .walk(s -> s.skip(2).findFirst())
                      .get()
                      .getMethodName();
}

StackWalkerआलसी होने के लिए डिज़ाइन किया गया है, इसलिए यह कहने की तुलना में अधिक कुशल होने की संभावना है, Thread.getStackTraceजो पूरे कॉलस्टैक के लिए उत्सुकता से एक सरणी बनाता है। अधिक जानकारी के लिए JEP भी देखें।


5

एक वैकल्पिक तरीका है, लेकिन फेंकना नहीं, एक अपवाद, और उस वस्तु का उपयोग करना जिससे स्टैक ट्रेस डेटा प्राप्त हो, क्योंकि एन्क्लोज़िंग विधि आमतौर पर सूचकांक 0 पर होगी - जब तक कि जेवीएम उस जानकारी को संग्रहीत नहीं करता है, जैसा कि अन्य के पास है। उपर्युक्त। हालांकि यह सबसे सस्ता तरीका नहीं है।

से Throwable.getStackTrace () (यह जावा 5 के बाद से ही कम से कम किया गया है):

सरणी का शून्य तत्व (मान की लंबाई गैर शून्य है) स्टैक के शीर्ष का प्रतिनिधित्व करता है, जो अनुक्रम में अंतिम विधि मंगलाचरण है। आमतौर पर , यह वह बिंदु है जिस पर यह फेंकने योग्य बनाया गया था और फेंक दिया गया था।

नीचे का स्निपेट वर्ग को गैर-स्थैतिक मानता है (क्योंकि गेटक्लास ()), लेकिन यह एक तरफ है।

System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());

4
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);

1
ऊपर mvanle virgo47 के उत्तर देखें और थोरबॉर्न-रावन-ऐर्सन की टिप्पणी करें। दोहराव, गैर-सटीक और गैर-विश्वसनीय कोड।
एलेक्सजेल

@ शिवाकोमुरवेल्ली हां, लेकिन किसी भी स्थिति में ऐसा नहीं लगता है, इसलिए मेरे से भी -1।
मार्टन बोडेवेस

3

मुझे इसका उपयोग करके समाधान मिल गया है (Android में)

/**
 * @param className       fully qualified className
 *                        <br/>
 *                        <code>YourClassName.class.getName();</code>
 *                        <br/><br/>
 * @param classSimpleName simpleClassName
 *                        <br/>
 *                        <code>YourClassName.class.getSimpleName();</code>
 *                        <br/><br/>
 */
public static void getStackTrace(final String className, final String classSimpleName) {
    final StackTraceElement[] steArray = Thread.currentThread().getStackTrace();
    int index = 0;
    for (StackTraceElement ste : steArray) {
        if (ste.getClassName().equals(className)) {
            break;
        }
        index++;
    }
    if (index >= steArray.length) {
        // Little Hacky
        Log.w(classSimpleName, Arrays.toString(new String[]{steArray[3].getMethodName(), String.valueOf(steArray[3].getLineNumber())}));
    } else {
        // Legitimate
        Log.w(classSimpleName, Arrays.toString(new String[]{steArray[index].getMethodName(), String.valueOf(steArray[index].getLineNumber())}));
    }
}

3

मुझे नहीं पता कि वर्तमान में निष्पादित विधि के नाम के पीछे क्या इरादा है, लेकिन अगर यह सिर्फ डिबगिंग उद्देश्य के लिए है, तो "लॉगबैक" जैसे लॉगिंग फ्रेमवर्क यहां मदद कर सकते हैं। उदाहरण के लिए, लॉगबैक में, आपको अपने लॉगिंग कॉन्फ़िगरेशन में पैटर्न "% M" का उपयोग करना होगा । हालाँकि, इसे सावधानी के साथ इस्तेमाल किया जाना चाहिए क्योंकि इससे प्रदर्शन में गिरावट आ सकती है।


2

यदि आप जानना चाहते हैं कि विधि किस नाम से जानी जाती है, तो आप कनिष्ठ परीक्षण विधि का उपयोग कर सकते हैं: https://stackoverflow.com/a/1426730/3076107


1
@AndreiKonstantinov मुझे नहीं लगता कि यह केवल लिंक है। यदि आप लिंक को हटा भी देते हैं, तो भी कम से कम कुछ जानकारी है।
EJoshuaS - मोनिका

1

यहां ज्यादातर उत्तर गलत लगते हैं।

    public static String getCurrentMethod() {
            return getCurrentMethod(1);
    }
    public static String getCurrentMethod(int skip) {
            return Thread.currentThread().getStackTrace()[1 + 1 + skip].getMethodName();
    }

उदाहरण:

    public static void main(String[] args) {
            aaa();
    }

    public static void aaa() {
            System.out.println("aaa  -> "  + getCurrentMethod( ) );
            System.out.println("aaa  -> "  + getCurrentMethod(0) );
            System.out.println("main -> "  + getCurrentMethod(1) );
    }

आउटपुट:

aaa  -> aaa
aaa  -> aaa
main -> main

आपके उपयोगी उत्तर के लिए धन्यवाद।
आम्रलीका

क्या आप स्पष्ट कर सकते हैं कि अधिकांश उत्तर आपके लिए गलत क्यों लगते हैं? कई उत्तर हैं और मैं उन सभी को पढ़ने और उनके और आपके उत्तर के बीच अंतर क्या है यह समझने के लिए जावा में अच्छी तरह से वाकिफ नहीं हूं। :(
Xobotun

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

0

मैंने मेकलमेनज़ के उत्तर को फिर से लिखा :

private static Method m;

static {
    try {
        m = Throwable.class.getDeclaredMethod(
            "getStackTraceElement",
            int.class
        );
    }
    catch (final NoSuchMethodException e) {
        throw new NoSuchMethodUncheckedException(e);
    }
    catch (final SecurityException e) {
        throw new SecurityUncheckedException(e);
    }
}


public static String getMethodName(int depth) {
    StackTraceElement element;

    final boolean accessible = m.isAccessible();
    m.setAccessible(true);

    try {
        element = (StackTraceElement) m.invoke(new Throwable(), 1 + depth);
    }
    catch (final IllegalAccessException e) {
        throw new IllegalAccessUncheckedException(e);
    }
    catch (final InvocationTargetException e) {
        throw new InvocationTargetUncheckedException(e);
    }
    finally {
        m.setAccessible(accessible);
    }

    return element.getMethodName();
}

public static String getMethodName() {
    return getMethodName(1);
}

-2
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();

11
कृपया अधिक जानकारी के साथ संपादित करें। कोड-ओनली एंड "ट्राय दिस" जवाबों को हतोत्साहित किया जाता है, क्योंकि उनमें कोई खोज योग्य सामग्री नहीं होती है, और यह नहीं समझाते कि किसी को "कोशिश" क्यों करनी चाहिए।
abarisone

1
हालाँकि यह कोड समस्या को हल करने में मदद कर सकता है, लेकिन यह इस बात की व्याख्या नहीं करता कि क्यों और / या यह कैसे उत्तर देता है। इस अतिरिक्त संदर्भ को प्रदान करने से इसके दीर्घकालिक शैक्षिक मूल्य में काफी सुधार होगा। कृपया स्पष्टीकरण जोड़ने के लिए अपने जवाब को संपादित करें, जिसमें सीमाएं और मान्यताएं शामिल हैं।
टोबी स्पाइट

1
केवल जावा 7+ के लिए, लेकिन विधि नाम प्राप्त करने के लिए संक्षिप्त तरीका। फिर भी, इस तरह के कॉल के प्रदर्शन के विचार बने हुए हैं।
बेंज

6
getEnclosingMethod()NullPointerExceptionजावा 7 में मेरे लिए फेंकता है
मार्कस एल

2
Java.lang.Class.getEnclosingMethod () एक विधि ऑब्जेक्ट देता है जो अंतर्निहित वर्ग के तुरंत घेरने की विधि का प्रतिनिधित्व करता है, यदि यह क्लास ऑब्जेक्ट किसी विधि के भीतर एक स्थानीय या अनाम वर्ग का प्रतिनिधित्व करता है, तो अन्य शून्य देता है।
स्टोव

-5

इस दृष्टिकोण में क्या गलत है:

class Example {
    FileOutputStream fileOutputStream;

    public Example() {
        //System.out.println("Example.Example()");

        debug("Example.Example()",false); // toggle

        try {
            fileOutputStream = new FileOutputStream("debug.txt");
        } catch (Exception exception) {
             debug(exception + Calendar.getInstance().getTime());
        }
    }

    private boolean was911AnInsideJob() {
        System.out.println("Example.was911AnInsideJob()");
        return true;
    }

    public boolean shouldGWBushBeImpeached(){
        System.out.println("Example.shouldGWBushBeImpeached()");
        return true;
    }

    public void setPunishment(int yearsInJail){
        debug("Server.setPunishment(int yearsInJail=" + yearsInJail + ")",true);
    }
}

और इससे पहले कि लोग System.out.println(...)आपको हमेशा उपयोग करने के बारे में पागल हो जाएं , और चाहिए, कुछ विधि बनाएं ताकि आउटपुट को पुनर्निर्देशित किया जा सके, जैसे:

    private void debug (Object object) {
        debug(object,true);
    }

    private void dedub(Object object, boolean debug) {
        if (debug) {
            System.out.println(object);

            // you can also write to a file but make sure the output stream
            // ISN'T opened every time debug(Object object) is called

            fileOutputStream.write(object.toString().getBytes());
        }
    }

4
@ आकाश मुझे ऐसा लग रहा है कि वास्तव में प्रश्न का उत्तर देने का प्रयास था। एक महान प्रयास नहीं है, लेकिन एक प्रयास कम नहीं है।
ivarni

@ivarni "एक अच्छा प्रयास नहीं"? इसके साथ गलत क्या है? आप "चुंबन सिद्धांत" से परिचित हैं?
जॉनी

@ आकाशम यह लफ्फाजी थी।
जॉनी

5
@ जॉनी कोडबेस में मेरे सामने अभी 271 कक्षाएं हैं। यहां तक ​​कि एक (कम अनुमान) और ओग 5 तरीके प्रति क्लास जो कि 1300 से अधिक तरीके हैं। और यह एक बड़ा कोडबेस भी नहीं है। आप अपने दृष्टिकोण को बढ़ाने के साथ समस्या नहीं देखते हैं? मैं असहमत होने से सहमत होकर काफी खुश हूं, लेकिन इसीलिए मैंने कहा कि यह अच्छा प्रयास नहीं है। यह किसी भी गैर-तुच्छ कोडबेस में भारी मात्रा में ओवरहेड का परिचय देता है।
ivarni

1
@ जॉनी मुझे लगता है कि मैंने बहुत से ऐसे मामले देखे हैं जहां विधि का नाम स्ट्रिंग से मेल नहीं खाता है जो मुझे डिबगिंग करते समय गलत दिशा में भेज दिया है। लेकिन जावा में मुझे अभी भी लगता है कि आपका सुझाव सबसे अच्छा है, अन्य विकल्प "लागत" बहुत अधिक है।
बस एक और रूपक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.