Mendapatkan nama metode yang sedang dijalankan

470

Apakah ada cara untuk mendapatkan nama metode yang sedang dijalankan di Jawa?

Omar Kooheji
sumber

Jawaban:

177

Thread.currentThread().getStackTrace()biasanya akan berisi metode Anda memanggilnya tetapi ada jebakan (lihat Javadoc ):

Beberapa mesin virtual mungkin, dalam beberapa keadaan, menghilangkan satu atau lebih bingkai tumpukan dari jejak tumpukan. Dalam kasus ekstrem, mesin virtual yang tidak memiliki informasi jejak tumpukan mengenai utas ini diizinkan untuk mengembalikan array nol panjang dari metode ini.

Bombe
sumber
7
Apakah perangkap yang sama ini berlaku untuk jejak tumpukan dalam pengecualian?
Nate Parsons
8
Ya itu. Dokumentasi untuk Throwable . [GetStackTrace ()] ( download.oracle.com/javase/1.5.0/docs/api/java/lang/... berisi paragraf yang sama persis.
Bombe
4
Yang mendasarinya adalah bahwa JVM tidak diharuskan untuk dapat menyediakan stacktrace, tetapi banyak pekerjaan telah dilakukan untuk membuat HotSpot sangat dapat diandalkan. Anda perlu tahu, jika Anda ingin kode Anda tidak bergantung pada perilaku JVM tertentu.
Thorbjørn Ravn Andersen
Versi Alexsmail di bawah ini tidak membuat jejak stack dan memberi Anda akses ke objek metode aktual, bukan hanya nama (sehingga Anda dapat mengetahui tipe pengembalian juga). Saya belum ditandai, tetapi saya curiga metodenya jauh lebih cepat karena jejak tumpukan cenderung mahal.
Gus
Respons Devin tampaknya memberikan jawaban yang jauh lebih ringkas untuk pertanyaan ini.
risingTide
310

Secara teknis ini akan berfungsi ...

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

Namun, kelas dalam anonim baru akan dibuat selama waktu kompilasi (misalnya YourClass$1.class). Jadi ini akan membuat .classfile untuk setiap metode yang menggunakan trik ini. Selain itu instance objek yang tidak digunakan dibuat pada setiap doa selama runtime. Jadi ini mungkin merupakan trik debug yang dapat diterima, tetapi ia datang dengan overhead yang signifikan.

Keuntungan dari trik ini adalah getEncosingMethod()pengembalian java.lang.reflect.Methodyang dapat digunakan untuk mengambil semua informasi lain dari metode termasuk anotasi dan nama parameter. Hal ini memungkinkan untuk membedakan antara metode tertentu dengan nama yang sama (kelebihan metode).

Perhatikan bahwa menurut JavaDoc getEnclosingMethod()trik ini tidak boleh membuang SecurityExceptionsebagai kelas dalam harus dimuat menggunakan loader kelas yang sama. Jadi tidak perlu memeriksa kondisi akses bahkan jika manajer keamanan hadir.

Diperlukan untuk digunakan getEnclosingConstructor()untuk konstruktor. Selama blok di luar metode (bernama), getEnclosingMethod()kembali null.

Devin
sumber
9
Ini tidak akan memberi Anda metode eksekusi saat ini. Ini akan memberi Anda metode di mana kelas anonim / lokal didefinisikan. - docs.oracle.com/javase/6/docs/api/java/lang/…
shrini1000
7
kelas Lokal {}; Nama string = Local.class.getEnclosingMethod (). GetName ();
alexsmail
21
@ shrini1000 idenya adalah menggunakan potongan ini di tempat informasi dibutuhkan, dan tidak memasukkannya ke rutin perpustakaan.
Thorbjørn Ravn Andersen
4
Terima kasih atas tipsnya! Alih-alih membuat objek baru, cukup gunakan this.getClass (). GetEnclosingMethod (). GetName ();
Lilo
3
@Lilo salah. getEnclosingMethodmendapat nama metode di mana kelas didefinisikan. this.getClass()tidak akan membantu Anda sama sekali. @wutzebaer mengapa Anda harus melakukannya? Anda sudah memiliki akses ke mereka.
Hazel Troost
134

Januari 2009:
Kode lengkap akan (untuk digunakan dengan peringatan @ Bombe dalam pikiran):

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

Lebih banyak di pertanyaan ini .

Pembaruan Desember 2011:

komentar kebiruan :

Saya menggunakan JRE 6 dan memberi saya nama metode yang salah.
Ini berfungsi jika saya menulisste[2 + depth].getMethodName().

  • 0adalah getStackTrace(),
  • 1adalah getMethodName(int depth)dan
  • 2 adalah metode yang memohon.

virgo47 's jawaban (upvoted) benar-benar menghitung indeks yang tepat untuk diterapkan dalam rangka untuk mendapatkan kembali nama metode.

VONC
sumber
2
Itu hanya mengatakan "utama" bagi saya. : - /
Kontrak Prof. Falken dilanggar
@Amigable: apakah Anda mencoba mencetak semua StackTraceElementarray untuk tujuan debugging dan untuk melihat apakah 'main' sebenarnya metode yang tepat?
VonC
7
Saya menggunakan JRE 6 dan memberi saya nama metode yang salah. Ini berfungsi jika saya menulis ste[2 + depth].getMethodName(). 0 adalah getStackTrace(), 1 adalah getMethodName(int depth)dan 2 adalah metode memohon. Lihat juga jawaban @ virgo47 .
kebiruan
2
@bluish: poin bagus. Saya telah memasukkan komentar Anda dan referensi untuk jawaban virgo47 di saya.
VonC
@VonC Apakah implementasi ini benar? kedalaman di sini harus ste.length +1 untuk itu memberikan metode saat ini. Tidakkah seharusnya menjadi [kedalaman + 1] jika kita ingin mengizinkan kedalaman = 0?
mmm
85

Kami menggunakan kode ini untuk mengurangi kemungkinan variabilitas dalam indeks jejak tumpukan - sekarang panggil saja methodName util:

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

Tampaknya overengineered, tetapi kami memiliki beberapa nomor tetap untuk JDK 1.5 dan sedikit terkejut itu berubah ketika kami pindah ke JDK 1.6. Sekarang sama di Jawa 6/7, tetapi Anda tidak pernah tahu. Ini bukan bukti perubahan indeks selama runtime - tetapi mudah-mudahan HotSpot tidak melakukan hal yang buruk. :-)

virgo47
sumber
1
Ini masih tergantung vendor. JVM tidak diharuskan untuk mengirimkan data yang dapat diandalkan untuk kode ini.
Thorbjørn Ravn Andersen
6
Sesuai spesifikasi JVM, JVM tidak diharuskan untuk menyediakan jejak stack penuh (optimasi, inlining, dan semua itu) dan Anda sudah menemukan bahwa heuristik Anda berubah antara Oracle Java 5 dan Oracle Java 6. Tidak ada yang menjamin bahwa JVM lain akan berperilaku seperti yang Anda harapkan dalam kode Anda, sehingga Anda secara halus mengandalkan perilaku spesifik vendor. Yang benar-benar baik-baik saja, selama Anda menyadarinya, tetapi jika - misalnya - Anda perlu menggunakan IBM JVM (yang harus kami lakukan) atau pada mesin Zing, Anda mungkin harus mengunjungi kembali heuristik Anda.
Thorbjørn Ravn Andersen
1
Ini tampaknya yang paling kuat dari semua opsi yang disajikan di sini, meskipun dependensi.
Ian
46
 public class SomeClass {
   public void foo(){
      class Local {};
      String name = Local.class.getEnclosingMethod().getName();
   }
 }

nama akan memiliki nilai foo.

alexsmail
sumber
5
Local.class.getEnclosingMethod () adalah null. jdk1.6.0_31, mainkan 1.2.5
eigil
@ eigil itu menarik tetapi tanpa info lebih lanjut, sulit untuk mengatakan apa yang "salah" atau kapan kita harapkannull
Maarten Bodewes
Ini trik yang sama dengan jawaban ini . Ini memiliki keuntungan bahwa itu tidak membuat contoh objek palsu, itu memiliki kelemahan bahwa itu memerlukan deklarasi kelas yang tidak dapat diuraikan dalam pernyataan (yaitu biasanya membutuhkan baris kode tambahan).
Maarten Bodewes
@ eigil apakah Anda mendefinisikan kelas di dalam kelas (contoh SomeClass), atau dalam metode (contoh foo)? Saya menemukan bahwa mendefinisikan subclass tanpa dibungkus dengan metode - atau dalam konstruktor - akan menyebabkan getEnclosingMethod () mengembalikan null.
DN
Cukup yakin saya melakukan persis seperti yang dijelaskan dalam jawaban ini. Saya pikir itu sesuatu yang aneh dengan playframework. Diuji dalam java 'normal' tanpa masalah.
eigil
36

Kedua opsi ini berfungsi untuk saya dengan Java:

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

Atau:

Thread.currentThread().getStackTrace()[1].getMethodName()
Charlie Seligman
sumber
1
untuk metode statis gunakan: <Class> .class.getEnclosingMethod (). getName ()
jellobird
hati-hati array kosong sesuai dengan jawaban Bombe dan indikasi javadoc. Beberapa JVM mungkin tidak mengisi array stacktrace?
el-teedee
34

Cara tercepat yang saya temukan adalah:

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

Ini mengakses metode asli getStackTraceElement (kedalaman int) secara langsung. Dan menyimpan Metode yang dapat diakses dalam variabel statis.


sumber
3
Tercepat dalam hal kinerja? Adakah tolok ukur mikro untuk mendukung klaim?
Ibrahim Arief
10
+1. Menggunakan loop waktu sederhana pada 1,6, 1.000.000 iterasi menggunakan metode ini mengambil 1219ms, sementara menggunakan new Throwable().getStackTrace()mengambil 5614ms.
ach
1
m.setAccessible (true); harus dikelilingi oleh AccessController.doPrivileged. Sesuatu untuk dipertimbangkan, bukan aturan keras yang akan saya katakan
avanderw
6
Diuji pada tahun 2016 dan ini terus menjadi yang tercepat. Seperti @ach, saya menggunakan iterasi 1M. 1.7_79: 1.6s vs 15.2s 1.8_74: 1.8s vs 16.0s. FWIW panjang tolok ukur ste array saya == 23 tetapi metode ini tetap cepat terlepas dari kedalaman tumpukan.
Ryan
25

Gunakan Kode berikut:

    StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
    StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
    String methodName = e.getMethodName();
    System.out.println(methodName);
Sumit Singh
sumber
2
Ini mencetak "getStackTrace" untuk saya - Saya menggunakan Java 1.5
Zack Macomber
hati-hati array kosong sesuai dengan jawaban Bombe dan indikasi javadoc. Beberapa JVM mungkin tidak mengisi array stacktrace?
el-teedee
16
public static String getCurrentMethodName() {
        return Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName();
    }
Jay
sumber
Ya, sejauh ini yang terbaik ... ubahlah menjadi metode dan dapatkan frame ketiga ([2]) (atau apa pun namanya) dalam jejak.
mike rodent
14

Ini adalah perluasan dari jawaban virgo47 (di atas).

Ini memberikan beberapa metode statis untuk mendapatkan nama kelas / metode saat ini dan memanggil.

/* 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 + ")";
    }
}
mvanle
sumber
3
Ini dikombinasikan dengan jawaban @ mklemenz adalah cara yang sangat cepat dan bersih untuk mengakses info tumpukan.
Octavia Togami
12

Untuk mendapatkan nama metode yang disebut metode saat ini, Anda dapat menggunakan:

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

Ini berfungsi pada MacBook saya dan juga pada ponsel Android saya

Saya juga mencoba:

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

tapi Android akan mengembalikan "getStackTrace" Saya bisa memperbaiki ini untuk Android

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

tapi kemudian saya mendapatkan jawaban yang salah di MacBook saya

Friso van der Made
sumber
Dalam pengujian baru-baru ini di Android, itu bekerja lebih baik bagi saya getStackTrace()[0]daripada menggunakan getStackTrace()[1]. YMMV.
mbm29414
untuk android adalahThread.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
    }
}
Maxple
sumber
final StackTraceElement e = Thread.currentThread().getStackTrace()[2]; bekerja; e.getClassName();kembalikan nama kelas penuh dan e.getMethodName()kembalikan nama methon.
Marks
1
getStackTrace()[2]salah, itu pasti getStackTrace()[3]karena: [0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3] Fungsi a () memanggil yang satu ini
PhilLab
11

Ini bisa dilakukan menggunakan StackWalkerJava 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();
}

StackWalkerdirancang untuk menjadi malas, sehingga cenderung lebih efisien daripada, katakanlah, Thread.getStackTraceyang dengan bersemangat membuat array untuk seluruh callstack. Lihat juga JEP untuk informasi lebih lanjut.

Radiodef
sumber
5

Metode alternatif adalah membuat, tetapi tidak melempar, Pengecualian, dan menggunakan objek itu untuk mendapatkan data jejak tumpukan, karena metode penutup biasanya akan berada di indeks 0 - selama JVM menyimpan informasi tersebut, seperti yang dimiliki orang lain. disebutkan di atas. Namun ini bukan metode termurah.

Dari Throwable.getStackTrace () (ini sudah sama sejak Java 5 setidaknya):

Elemen nol dari array (dengan asumsi panjang array adalah nol) mewakili bagian atas tumpukan, yang merupakan doa metode terakhir dalam urutan. Biasanya , ini adalah titik di mana lemparan ini dibuat dan dilemparkan.

Cuplikan di bawah ini menganggap kelas adalah non-statis (karena getClass ()), tapi itu samping.

System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
Jool
sumber
4
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
berlari
sumber
1
Lihat jawaban mvanle virgo47 di atas dan komentar thorbjorn-ravn-andersen. Pengulangan, kode tidak akurat dan tidak dapat diandalkan.
alexsmail
@ShivaKomuravelly Ya, tapi tidak dalam situasi apa pun, jadi -1 dari saya juga.
Maarten Bodewes
3

Saya punya solusi menggunakan ini (dalam 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())}));
    }
}
Kasim Rangwala
sumber
3

Saya tidak tahu apa maksud di balik mendapatkan nama metode yang saat ini dieksekusi, tetapi jika itu hanya untuk tujuan debugging, maka kerangka kerja logging seperti "logback" dapat membantu di sini. Misalnya, dalam logback, yang perlu Anda lakukan adalah menggunakan pola "% M" dalam konfigurasi logging Anda . Namun, ini harus digunakan dengan hati-hati karena ini dapat menurunkan kinerja.

James Selvakumar
sumber
2

Untuk berjaga-jaga jika metode yang namanya ingin Anda ketahui adalah metode uji junit, maka Anda dapat menggunakan aturan Junit TestName: https://stackoverflow.com/a/1426730/3076107

Egl
sumber
1
@AndreiKonstantinov Saya tidak berpikir bahwa ini hanya tautan. Bahkan jika Anda menghapus tautan, masih ada setidaknya beberapa informasi untuk melanjutkan.
EJoshuaS
1

Sebagian besar jawaban di sini tampaknya salah.

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

Contoh:

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

Output:

aaa  -> aaa
aaa  -> aaa
main -> main
mmm
sumber
Terima kasih atas jawaban Anda yang bermanfaat.
AmerllicA
Bisakah Anda menjelaskan mengapa sebagian besar jawaban tampaknya salah bagi Anda? Ada banyak jawaban dan saya tidak begitu berpengalaman di Jawa untuk membaca semuanya dan untuk memahami apa perbedaan antara mereka dan jawaban Anda. :(
Xobotun
@mmm Maaf, tapi saya sangat tidak setuju. Saya datang ke sini untuk belajar dan begitu juga banyak orang lain, saya percaya. Saya hanya tidak mengerti mengapa Anda pikir saya tidak pantas tahu lebih banyak tentang hal ini. Saya ingin membuat lebih sedikit kesalahan dalam kode saya dan untuk memperingatkan orang lain, bukan untuk mengikuti kultus kargo. Anda setidaknya bisa mengklarifikasi versi Java mana dari kode ini yang seharusnya benar. :( Sebuah jawaban di bawah ini mengatakan ada perubahan dalam stacktrace antara 1,5 dan 1,6. Mungkin Anda menyiratkan ada sesuatu seperti itu di Java 14 mendatang, bagaimana saya bisa tahu. Atau mungkin ada vendor yang berbeda. Maaf jika saya salah mengartikan jawaban Anda sebagai kasar satu
Xobotun
0

Saya menulis ulang sedikit jawaban maklemenz :

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);
}
Marco Sulla
sumber
-2
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
Darren
sumber
11
Harap edit dengan informasi lebih lanjut. Jawaban khusus kode dan "coba ini" tidak disarankan, karena tidak mengandung konten yang dapat ditelusuri, dan jangan jelaskan mengapa seseorang harus "coba ini".
abarisone
1
Meskipun kode ini dapat membantu menyelesaikan masalah, kode ini tidak menjelaskan mengapa dan / atau bagaimana ia menjawab pertanyaan. Memberikan konteks tambahan ini akan secara signifikan meningkatkan nilai pendidikan jangka panjangnya. Harap edit jawaban Anda untuk menambahkan penjelasan, termasuk batasan dan asumsi apa yang berlaku.
Toby Speight
1
Hanya untuk Java 7+, tetapi cara ringkas untuk mendapatkan nama metode. Namun, tetap pertimbangan kinerja panggilan semacam itu.
Benj
6
getEnclosingMethod()melempar NullPointerExceptionuntuk saya di Jawa 7.
Markus L
2
Java.lang.Class.getEnclosingMethod () mengembalikan objek Metode yang mewakili metode segera melampirkan dari kelas yang mendasarinya, jika objek Kelas ini mewakili kelas lokal atau anonim dalam suatu metode, yang lain mengembalikan nol.
kompor
-5

Apa yang salah dengan pendekatan ini:

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

Dan sebelum orang tergila-gila menggunakan System.out.println(...)Anda selalu, dan harus, membuat beberapa metode sehingga output dapat diarahkan, misalnya:

    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());
        }
    }
johnny
sumber
4
@ Saksham bagi saya sepertinya itu adalah upaya untuk menjawab pertanyaan. Bukan upaya yang hebat, tapi upaya yang tidak kalah.
ivarni
@ivarni "bukan upaya yang baik"? Apakah ada yang salah? apakah Anda akrab dengan "prinsip ciuman"?
johnny
@ Saksham itu retoris.
johnny
5
@ Johnny Dalam basis kode yang saya miliki di depan saya sekarang ada 271 kelas. Bahkan dengan (estimasi rendah) dan 5 metode per kelas itu lebih dari 1.300 metode. Dan ini bahkan bukan basis kode besar. Anda tidak melihat masalah dengan meningkatkan pendekatan Anda? Saya cukup senang setuju untuk tidak setuju, tapi itu sebabnya saya mengatakan itu bukan upaya yang baik. Ini memperkenalkan sejumlah besar overhead dalam basis kode apa pun non-sepele.
ivarni
1
@ Johnny Saya kira saya telah melihat terlalu banyak kasus di mana nama metode tidak cocok dengan string yang telah mengirim saya ke arah yang salah ketika debugging. Tetapi di Jawa saya masih berpikir saran Anda adalah yang terbaik, alternatif lain "terlalu mahal".
Hanya pembuat program lain