回答:
Thread.currentThread().getStackTrace()
通常、呼び出し元のメソッドが含まれますが、落とし穴があります(Javadocを参照)。
一部の仮想マシンは、状況によっては、スタックトレースから1つ以上のスタックフレームを省略します。極端な場合、このスレッドに関するスタックトレース情報を持たない仮想マシンは、このメソッドから長さ0の配列を返すことが許可されます。
技術的にはこれでうまくいきます...
String name = new Object(){}.getClass().getEnclosingMethod().getName();
ただし、新しい匿名内部クラスはコンパイル時に作成されます(例:)YourClass$1.class
。したがって、これにより、.class
このトリックを展開する各メソッドのファイルが作成されます。さらに、それ以外の場合は未使用のオブジェクトインスタンスが、実行時の呼び出しごとに作成されます。したがって、これは許容できるデバッグトリックかもしれませんが、かなりのオーバーヘッドが伴います。
このトリックの利点は、あるgetEncosingMethod()
リターンjava.lang.reflect.Method
注釈やパラメータ名を含む、方法の他のすべての情報を取得するために使用することができます。これにより、同じ名前の特定のメソッドを区別できます(メソッドオーバーロード)。
getEnclosingMethod()
このトリックのJavaDocによると、SecurityException
内部クラスは同じクラスローダーを使用してロードする必要があるため、をスローしないでください。したがって、セキュリティマネージャーが存在する場合でも、アクセス条件を確認する必要はありません。
getEnclosingConstructor()
コンストラクターに使用する必要があります。(名前付き)メソッド外のブロック中、getEnclosingMethod()
返しますnull
。
getEnclosingMethod
クラスが定義されているメソッドの名前を取得します。this.getClass()
まったくあなたを助けません。@wutzebaerなぜあなたもする必要がありますか?あなたはすでにそれらにアクセスできます。
2009年1月:
完全なコードは次のようになります(@Bombeの警告を念頭に置いて使用します):
/**
* 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年12月の更新:
青みがかったコメント:
JRE 6を使用していますが、メソッド名が間違っています。
私が書けばうまくいくste[2 + depth].getMethodName().
0
はgetStackTrace()
、1
でありgetMethodName(int depth)
、2
メソッドを呼び出しています。
StackTraceElement
デバッグ目的でall 配列を出力して、「main」が実際に正しい方法であるかどうかを確認しようとしましたか?
ste[2 + depth].getMethodName()
。0はgetStackTrace()
、1はgetMethodName(int depth)
、2はメソッドを呼び出します。@ virgo47の回答も参照してください。
このコードを使用して、スタックトレースインデックスの潜在的な変動を緩和しました。今は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();
}
}
過剰に設計されているようですが、JDK 1.5にはいくつかの固定数があり、JDK 1.6に移行したときに変更されたことに少し驚いていました。今ではJava 6/7でも同じですが、あなたは決して知りません。実行時にそのインデックスが変更されることを証明するものではありませんが、HotSpotがそれほどうまく機能しないことを願っています。:-)
public class SomeClass {
public void foo(){
class Local {};
String name = Local.class.getEnclosingMethod().getName();
}
}
名前の値はfooです。
null
これらのオプションはどちらも、Javaで動作します。
new Object(){}.getClass().getEnclosingMethod().getName()
または:
Thread.currentThread().getStackTrace()[1].getMethodName()
私が見つけた最速の方法はそれです:
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 depth)に直接アクセスします。アクセス可能なメソッドを静的変数に格納します。
new Throwable().getStackTrace()
5614ミリ秒かかりました。
次のコードを使用します。
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
String methodName = e.getMethodName();
System.out.println(methodName);
これは、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 + ")";
}
}
現在のメソッドを呼び出したメソッドの名前を取得するには、以下を使用できます。
new Exception("is not thrown").getStackTrace()[1].getMethodName()
これは私のMacBookと私のAndroidフォンで動作します
私も試しました:
Thread.currentThread().getStackTrace()[1]
しかし、Androidは「getStackTrace」を返します。
Thread.currentThread().getStackTrace()[2]
MacBookで間違った答えが出る
getStackTrace()[0]
よりも、使用する方がうまくいきましたgetStackTrace()[1]
。YMMV。
Thread.currentThread().getStackTrace()[2]
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()
メソッド名を返します。
getStackTrace()[2]
間違っている、それがなければならないgetStackTrace()[3]
ので、[0] dalvik.system.VMStack.getThreadStackTrace [1] java.lang.Thread.getStackTrace [2] Utils.getCurrentClassAndMethodNames [3]機能()は、このいずれかを呼び出す
これはStackWalker
Java 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も参照してください。
別の方法は、例外を作成するがスローしないで、スタックトレースデータを取得するためにそのオブジェクトを使用することです。これは、囲んでいるメソッドが通常はインデックス0にあるためです。上記の通り。ただし、これは最も安価な方法ではありません。
Throwable.getStackTrace()から(これは少なくともJava 5以降同じです):
配列の0番目の要素(配列の長さが0でない場合)は、スタックの最上位を表します。これは、シーケンスの最後のメソッド呼び出しです。通常、これは、このスロー可能オブジェクトが作成されてスローされたポイントです。
以下のスニペットは、クラスが静的でない(getClass()のため)と想定していますが、それはさておきます。
System.out.printf("Class %s.%s\n", getClass().getName(), new Exception("is not thrown").getStackTrace()[0].getMethodName());
String methodName =Thread.currentThread().getStackTrace()[1].getMethodName();
System.out.println("methodName = " + methodName);
これを使用して解決策があります(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())}));
}
}
現在実行されているメソッドの名前を取得する目的は何なのかわかりませんが、それがデバッグ目的だけの場合は、「logback」などのロギングフレームワークが役立ちます。たとえば、logbackでは、ログ構成でパターン "%M"を使用するだけです。ただし、これはパフォーマンスを低下させる可能性があるため、注意して使用する必要があります。
念のためにあなたが知りたい名前メソッドは、JUnitテストメソッドがあり、その後、あなたはのJUnitテスト名規則を使用することができます。https://stackoverflow.com/a/1426730/3076107
ここでのほとんどの答えは間違っているようです。
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
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);
}
MethodHandles.lookup().lookupClass().getEnclosingMethod().getName();
getEnclosingMethod()
NullPointerException
Java 7でa をスローします
このアプローチの何が問題になっています:
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());
}
}