Yürütülmekte olan yöntemin adını alma


Yanıtlar:


177

Thread.currentThread().getStackTrace()genellikle çağırdığınız yöntemi içerir, ancak tuzaklar vardır (bkz. Javadoc ):

Bazı sanal makineler, bazı durumlarda, yığın izlemeden bir veya daha fazla yığın çerçevesini atlayabilir. Aşırı durumda, bu iş parçacığıyla ilgili yığın izleme bilgisi olmayan bir sanal makinenin bu yöntemden sıfır uzunluklu bir dizi döndürmesine izin verilir.


7
İstisnalarda yığın izleri için de aynı tuzak var mı?
Nate Parsons

8
Evet öyle. Throwable belgeleri . [GetStackTrace ()] ( download.oracle.com/javase/1.5.0/docs/api/java/lang/… tam olarak aynı paragrafı içerir.
Bombe

4
Altta yatan şey, JVM'nin bir yığın izlemesi sağlayabilmesi gerekmediği , ancak HotSpot'u çok güvenilir hale getirmek için çok fazla işin yapıldığıdır. Bununla birlikte, kodunuzun belirli bir JVM'nin davranışına güvenmemesini istemeniz durumunda bilmeniz gerekir.
Thorbjørn Ravn Andersen

Alexsmail'in aşağıdaki sürümü bir yığın izlemesi oluşturmaz ve yalnızca adı değil gerçek yöntem nesnesine erişmenizi sağlar (böylece dönüş türünü de bulabilirsiniz). Ben tezgah işaretlemedim ama yığın izleri pahalı olma eğiliminde olduğundan yönteminin çok daha hızlı olduğundan şüpheleniyorum.
Gus

Devin'un cevabı bu soruya çok daha özlü bir cevap veriyor gibi görünüyor.
risingTide

310

Teknik olarak bu işe yarayacak ...

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

Ancak, derleme zamanında yeni bir anonim iç sınıf oluşturulacaktır (örn. YourClass$1.class). Bu, .classbu hileyi dağıtan her yöntem için bir dosya oluşturur . Ayrıca, çalışma zamanı sırasında her çağrıda başka bir şekilde kullanılmayan bir nesne örneği oluşturulur. Yani bu kabul edilebilir bir hata ayıklama hilesi olabilir, ancak önemli bir ek yük ile birlikte gelir.

Bu hilenin bir avantajı, ek açıklamalar ve parametre adları da dahil olmak üzere yöntemin diğer tüm bilgilerini almak için kullanılabilen getEncosingMethod()getirilerdir java.lang.reflect.Method. Bu, aynı ada sahip belirli yöntemler (yöntem aşırı yüklenmesi) arasında ayrım yapmayı mümkün kılar.

getEnclosingMethod()Bu SecurityExceptionsınıfın JavaDoc ' a göre iç sınıflar aynı sınıf yükleyici kullanılarak yüklenmelidir. Bu nedenle, bir güvenlik yöneticisi mevcut olsa bile erişim koşullarını kontrol etmeye gerek yoktur.

Yapıcılar için kullanılması gerekir getEnclosingConstructor(). (Adlandırılmış) yöntemlerin dışındaki bloklar sırasında getEnclosingMethod()döndürür null.


9
Bu, şu anda yürütme yöntemini vermeyecektir. Bu size anonim / yerel bir sınıfın tanımlandığı yöntemi verecektir. - docs.oracle.com/javase/6/docs/api/java/lang/…
shrini1000

7
sınıf Yerel {}; Dize adı = Local.class.getEnclosingMethod (). GetName ();
alexsmail

21
@ shrini1000 fikir bu snippet'i bilginin gerekli olduğu yerlerde kullanmak ve bir kütüphane rutininin içine koymak değildir.
Thorbjørn Ravn Andersen

4
İpuçları için teşekkürler ! Yeni bir nesne oluşturmak yerine, this.getClass (). GetEnclosingMethod (). GetName ();
Lilo

3
@Lilo yanlış. getEnclosingMethodsınıfın tanımlandığı yöntemin adını alır. this.getClass()sana hiç yardım etmeyecek. @wutzebaer neden gerek bile? Bunlara zaten erişiminiz var.
Hazel Troost

134

Ocak 2009:
Tam kod ( @ Bombe'un uyarısı göz önünde bulundurularak kullanılacak) olacaktır:

/**
 * 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
}

Bu soruda daha fazlası .

Aralık 2011 Güncellemesi:

mavimsi yorumlar:

JRE 6 kullanıyorum ve bana yanlış yöntem adı veriyor.
Yazarsam çalışırste[2 + depth].getMethodName().

  • 0olduğunu getStackTrace(),
  • 1olduğu getMethodName(int depth)ve
  • 2 yöntemi çağırıyor.

virgo47 'ın cevabı (upvoted) aslında yöntem adını geri almak için uygulamak için sağ endeksi hesaplar.


2
Benim için sadece "ana" yazıyor. : - /
Prof. Falken sözleşmesi

@Amigable: Tüm StackTraceElementdiziyi hata ayıklama amacıyla yazdırmaya ve 'main' öğesinin gerçekten doğru yöntem olup olmadığını görmeye çalıştınız mı?
VonC

7
JRE 6 kullanıyorum ve bana yanlış yöntem adı veriyor. Ben yazarsam çalışır ste[2 + depth].getMethodName(). 0 getStackTrace(), 1 getMethodName(int depth)ve 2 çağrı yöntemidir. Ayrıca bkz. @ Virgo47'nin yanıtı .
mavimsi

2
@bluish: iyi bir nokta. Yorumunuzu ve virgo47'nin benimkine cevabına bir referans ekledim.
VonC

@VonC Bu uygulama gerçekten doğru mu? Buradaki derinliği verebilmek için derinlik ste.length + 1 olmalıdır. Derinliğe izin verirsek ste [derinlik + 1] olmamalı mı = 0?
mmm

86

Bu kodu yığın izleme dizinindeki olası değişkenliği azaltmak için kullandık - şimdi methodName util'i çağırmanız yeterli:

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();
    }
}

Görünüşe bakılırsa JDK 1.5 için sabit bir sayıya sahiptik ve JDK 1.6'ya taşındığımızda değiştiğine biraz şaşırdık. Şimdi Java 6/7'de de aynı, ama asla bilemezsiniz. Çalışma sırasında bu dizindeki değişikliklerin kanıtı değildir - ancak umarım HotSpot bunu kötü yapmaz. :-)


1
Bu hala satıcıya bağımlıdır. JVM, bu kod için güvenilir veri sağlamak zorunda değildir.
Thorbjørn Ravn Andersen

6
JVM spesifikasyonlarına göre JVM'nin tam yığın izleri (optimizasyon, satır içi ve tüm bunlar) sağlaması gerekmez ve buluşsal yönteminizin Oracle Java 5 ve Oracle Java 6 arasında değiştiğini zaten keşfettiniz. kodunuzda beklediğiniz gibi davrandığından, satıcıya özgü davranışlara hassas bir şekilde güveniyorsunuzdur. Bu, bildiğiniz sürece gayet iyi, ancak örneğin - bir IBM JVM'ye (ki biz yapmamız gerekir) veya bir Zing örneğine konuşlandırmanız gerekiyorsa, sezgisel çözümünüzü yeniden ziyaret etmeniz gerekebilir.
Thorbjørn Ravn Andersen

1
Bu, burada sunulan tüm seçeneklerden en sağlamı, bağımlılıklara rağmen görünmüyor.
Ian

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

ad foo değerine sahip olacaktır.


5
Local.class.getEnclosingMethod () boş. jdk1.6.0_31, oyun 1.2.5
eigil

@eigil bu ilginç ama daha fazla bilgi olmadan ne "yanlış" gittiğini ya da ne zaman beklemek gerekir söylemek zornull
Maarten Bodewes

Bu cevapla aynı hile . Sahte bir nesne örneği oluşturmaması avantajına sahiptir, ifadede satır içine alınamayan bir sınıf bildirimi gerektirmesi dezavantajına sahiptir (normalde ek bir kod satırı gerektirir).
Maarten Bodewes

@eigil sınıfı bir sınıf içinde (örnek SomeClass) veya bir yöntem içinde (örnek foo) tanımladınız mı? Bir yöntemde veya bir kurucuda sarılmadan bir alt sınıf tanımlamanın getEnclosingMethod () işlevinin null döndürmesine neden olacağını buldum.
DN

Kesinlikle bu cevapta açıklandığı gibi yaptım. Bence bu oyun çerçevesiyle garip bir şey. Herhangi bir sorun olmadan 'normal' java test edilmiştir.
eigil

36

Bu seçeneklerin ikisi de Java ile benim için çalışıyor:

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

Veya:

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

1
statik yöntemler için: <Class> .class.getEnclosingMethod ().
getName

Bombe'nin cevabına ve javadoc göstergesine göre boş diziye dikkat edin. Bazı JVM stacktrace dizisini doldurmayabilir?
el-teedee

34

Bulduğum en hızlı yol :

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;
        }
    }
}

Doğrudan getStackTraceElement (int deep) yöntemine erişir. Ve erişilebilir Yöntemi statik bir değişkende saklar.


3
Performans açısından en hızlı şekilde? Hak talebini destekleyen herhangi bir mikro kriter var mı?
Ibrahim Arief

10
+1. 1.6 üzerinde basit bir zamanlanmış döngü kullanarak, bu yöntemi kullanarak 1.000.000 yineleme 1219ms alırken new Throwable().getStackTrace(), 5614ms aldı.
ach

1
m.setAccessible (doğru); AccessController.doPrivileged ile çevrelenmelidir. Dikkate değer bir şey, söyleyeceğim zor bir kural değil
avanderw

6
2016 yılında test edildi ve bu en hızlı olmaya devam ediyor. @Ach gibi 1M yinelemeleri kullandım. 1.7_79: 1.6s ve 15.2s 1.8_74: 1.8s vs 16.0s. FWIW benim test ste dizinin uzunluğu == 23 ancak bu yöntem yığın derinliğine bakılmaksızın hızlı kalır.
Ryan

25

Aşağıdaki Kodu kullanın:

    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
Bu benim için "getStackTrace" yazdırır - Java 1.5 kullanıyorum
Zack Macomber

Bombe'nin cevabına ve javadoc göstergesine göre boş diziye dikkat edin. Bazı JVM stacktrace dizisini doldurmayabilir?
el-teedee

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

Evet, en iyisi ... bir yönteme dönüştürün ve izdeki üçüncü ([2]) çerçeveyi (ya da her ne denirse) alın.
mike kemirgen

14

Bu, virgo47'nin cevabındaki bir genişlemedir (yukarıda).

Geçerli ve çağıran sınıf / yöntem adlarını almak için bazı statik yöntemler sağlar.

/* 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
Bu @ mklemenz'in cevabı ile birlikte yığın bilgilerine erişmenin çok hızlı ve temiz bir yoludur.
Octavia Togami

12

Geçerli yöntemi çağıran yöntemin adını almak için şunları kullanabilirsiniz:

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

Bu, MacBook'umda ve Android telefonumda çalışıyor

Ayrıca denedim:

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

ancak Android "getStackTrace" i döndürecektir.

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

ama sonra MacBook'umda yanlış cevap alıyorum


Android'de yapılan son testlerde, kullanmak getStackTrace()[0]yerine benim için daha iyi çalıştı getStackTrace()[1]. YMMV.
mbm29414

kadar androidThread.currentThread().getStackTrace()[2]
Ninja

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]; İşler; e.getClassName();sınıfın tamamını e.getMethodName()döndürün ve yöntem adını döndürün.
Marks

1
getStackTrace()[2]yanlış, bu olmak zorundadır getStackTrace()[3], çünkü: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] fonksiyonu () bu bir çağrı
PhilLab

11

Bu StackWalkerJava 9'dan beri yapılabilir .

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();
}

StackWalkertembel olacak şekilde tasarlanmıştır, bu nedenle Thread.getStackTrace, tüm çağrı istasyonu için hevesle bir dizi oluşturan , örneğin daha verimli olması muhtemeldir . Ayrıca daha fazla bilgi için JEP'e bakın.


5

Alternatif bir yöntem, bir Özel Durum oluşturmak, ancak atmak değil ve yığın izleme verilerinin alınacağı nesneyi kullanmaktır, çünkü kapalı yöntem tipik olarak 0 dizininde olacaktır - JVM bu bilgileri depoladığı sürece, diğerleri yukarıda bahsedilen. Ancak bu en ucuz yöntem değil.

Gönderen Throwable.getStackTrace () (bu en azından Java 5 beri aynı olmuştur):

Dizinin sıfırıncı öğesi (dizinin uzunluğunun sıfır olmadığı varsayılarak), dizideki son yöntem çağrısı olan yığının en üstünü temsil eder. Tipik olarak , bu atılabilir maddenin yaratıldığı ve atıldığı noktadır.

Aşağıdaki snippet, sınıfın statik olmadığını varsayar (getClass () nedeniyle), ancak bu bir yana.

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'nin cevaplarına bakın ve thorbjorn-ravn-andersen hakkında yorum yapın. Tekrarlama, doğru olmayan ve güvenilir olmayan kod.
alexsmail

@ShivaKomuravelly Evet, ancak göründüğü gibi değil, benden de -1.
Maarten Bodewes

3

Bunu kullanarak çözümüm var (Android'de)

/**
 * @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

Şu anda yürütülen yöntemin adını almanın arkasındaki niyetin ne olduğunu bilmiyorum, ancak bu sadece hata ayıklama amaçlıysa, "logback" gibi çerçevelerin kaydedilmesi burada yardımcı olabilir. Örneğin, geri oturum açmada tek yapmanız gereken günlük yapılandırmanızda "% M" desenini kullanmaktır . Ancak, performansı düşürebileceğinden bu durum dikkatli kullanılmalıdır.



1

Buradaki cevapların çoğu yanlış görünüyor.

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

Misal:

    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) );
    }

Çıktılar:

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

Yararlı cevabınız için teşekkürler.
AmerllicA

Çoğu cevabın neden sizin için yanlış göründüğünü açıklar mısınız? Birçok cevap var ve hepsini okumak ve cevabınız arasındaki farkın ne olduğunu anlamak için Java'da bu kadar bilgili değilim. :(
Xobotun

@mmm Üzgünüm, ama kesinlikle katılmıyorum. Buraya öğrenmek için geliyorum ve diğerleri gibi inanıyorum. Neden bu konuda daha fazla bilgi sahibi olmayı hak etmediğimi anlayamıyorum. Kodumda daha az hata yapmak ve başkalarını uyarmak istiyorum, kargo kültünü takip etmemek. En azından bu kodun hangi Java sürümünün doğru olması gerektiğini açıklığa kavuşturabilirsiniz. :( Aşağıdaki bir yanıt, yığın izlemede 1,5 ile 1,6 arasında bir değişiklik olduğunu söylüyor.Belki önümüzdeki Java 14'te böyle bir şey olduğunu, nasıl bilebilirim ya da farklı bir satıcı olabilir. biri.
Xobotun

0

Maklemenz'in cevabını biraz yeniden yazdım :

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
Lütfen daha fazla bilgi ile düzenleyin. Yalnızca kod ve "bunu dene" yanıtları önerilmez çünkü bunlar aranabilir içerik içermez ve birisinin neden "bunu denemesi" gerektiğini açıklamaz.
abarisone

1
Bu kod sorunu çözmeye yardımcı olsa da , soruyu neden ve / veya nasıl cevapladığını açıklamaz . Bu ek bağlamın sağlanması, uzun vadeli eğitim değerini önemli ölçüde artıracaktır. Hangi sınırlamalar ve varsayımlar dahil olmak üzere açıklama eklemek için lütfen yanıtınızı düzenleyin .
Toby Speight

1
Sadece Java 7+ için, ancak yöntem adını almanın özlü yolu. Yine de, böyle bir çağrının performans hususları kalır.
Benj

6
getEnclosingMethod()NullPointerExceptionJava 7'de benim için bir atar .
Markus L

2
Java.lang.Class.getEnclosingMethod (), temel alınan sınıfın hemen çevreleme yöntemini temsil eden bir Method nesnesi döndürür; bu Class nesnesi, bir yöntem içindeki yerel veya anonim sınıfı temsil ediyorsa, aksi takdirde null değerini döndürür.
ocak

-5

Bu yaklaşımda sorun nedir:

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);
    }
}

Ve insanlar kullanım konusunda çıldırmadan önce System.out.println(...), çıktının yeniden yönlendirilebilmesi için her zaman bir yöntem oluşturabilir ve etmelisiniz, örneğin:

    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
@Saksham bana bu aslında soruyu cevaplama girişimi gibi görünüyor. Büyük bir girişim değil, ama bir girişim daha az.
ivarni

@ivarni "iyi bir girişim değil" mi? bunun nesi var? "öpücük ilkesine" aşina mısınız?
johnny

@Saksham retorikti.
johnny

5
@johnny Şu an önümde olan kod tabanında 271 ders var. Sınıf başına (düşük tahmin) og 5 yöntemiyle bile 1300'den fazla yöntemdir. Ve bu büyük bir kod tabanı bile değil. Yaklaşımınızı büyütmeyle ilgili bir sorun görmüyor musunuz? Katılmayı kabul etmekten oldukça mutluyum, ama bu yüzden iyi bir girişim olmadığını söyledim. Önemsiz herhangi bir kod tabanına büyük miktarda ek yük getirir.
ivarni

1
@johnny Yöntem adının hata ayıklama sırasında beni yanlış yönde gönderen dizeyle eşleşmediği çok fazla durum gördüm sanırım. Ancak Java'da hala önerilerinizin en iyisi olduğunu düşünüyorum, diğer alternatifler çok pahalıya mal oluyor.
Başka bir meta programcı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.