こんにちは!侍エンジニア インストラクターの本多です。
Javaのコーディングにおいて、実行したメソッド名やクラス名を取得したい、ということがよくあります。
Log4j等のデバッグツールを入れるとよいのはわかるが面倒!ちょっと知りたいだけなのに・・・という場合もありますよね。
この記事では、メソッド名やクラス名を取得する方法について
・スタックトレースとは何か?
・実行中のクラスからクラス名を取得する方法
・実行中のクラスからメソッド名を取得する方法
という基本的な内容から、
・スタックトレースからクラス名を取得する方法
・スタックトレースからメソッド名を取得する方法
といった応用的な内容に関しても解説していきます。
今回はメソッド名やクラス名を取得する方法について、使い方をわかりやすく解説します!
なお、Javaの記事については、こちらにまとめています。
スタックトレースとは
私たちが書いたJavaのプログラムは、コンパイラによってJVM ( Java Vitrual Machine ) が理解できるバイナリコードに変換されます。
JVM は、バイナリコードをさらにOSが理解できるネイティブコードに変換します。
JVM が使うメモリ領域は、大きく分けてヒープ領域、スタック領域の2つがあります。
スタック領域には、クラスやメソッドの情報が入ります。
通常、プログラムとは1つのクラス、1つのメソッドで目的を果たせることはほぼなく、クラスやメソッドが呼びに呼ばれて、、、となってようやく目的を果たせます。
クラスやメソッドが呼ばれるたびに、その情報がスタック領域に積み上がります。
それが「スタックトレース」です。
JVM について、もっと知りたい方は以下をご覧ください。
クラス名を取得する方法
クラス名を取得する方法は2つあります。
実行中のクラス自身に記述して取得する方法と、スタックトレースから取得する方法です。
実行中のクラスから取得する方法
実行中のクラスからクラス名を取得する方法を、次のプログラムで確認してみましょう。
public class GetClassNameSample1 { public static void main(String[] args) { String className = new Object(){}.getClass().getName(); System.out.println(className); } }
実行結果:
GetClassNameSample1$1
この方法では、実行結果のように末尾に$1が入ります。
末尾の$1を消すためには、以下のようにしてください。
一部抜粋:
String className = new Object(){}.getClass().getEnclosingClass().getName();
実行結果:
GetClassNameSample1
スタックトレースから取得する方法
冒頭で説明したスタックトレースを使う方法です。
public class GetClassNameSample2 { public static void main(String[] args) { String className = Thread.currentThread().getStackTrace()[1].getClassName(); System.out.println(className); } }
実行結果:
GetClassNameSample2
getStackTrace() は、スタックの内容を配列で返します。
よってインデックス番号を[1]と指定することにより、自身のクラス名を取得することが可能です。
ちなみに、0はThreadそのもののクラスjava.lang.Threadを返します。
2を指定すると自身より下のスタックを探しに行きますが、まだ無いためArrayIndexOutOfBoundsExceptionの例外が発生します。
実行結果:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2 at GetClassNameSample2.main(GetClassNameSample2.java:5)
メソッド名を取得する方法
メソッド名も同様に、実行中のクラス内で取得する方法と、スタックトレースから取得する方法があります。
実行中のクラスから取得する方法
実行中のクラスからメソッド名を取得する方法を、次のプログラムで確認してみましょう。
public class GetMethodNameSample1 { public static void main(String[] args) { String methodName = new Object(){}.getClass().getEnclosingMethod().getName(); System.out.println(methodName); } }
実行結果:
main
部分的にclassからmethodに変えただけで完結します。
スタックトレースから取得する方法
これも基本的な考え方はクラスの時と同じです。
public class GetMethodNameSample2 { public static void main(String[] args) { String methodName = Thread.currentThread().getStackTrace()[1].getMethodName(); System.out.println(methodName); } }
実行結果:
main
getStackTrace()[1]のインデックス番号を、0,1,2と変えるとどうなるでしょうか?
クラス名取得のときと同様、0ではgetStackTrace、1はmain、2のときはArrayIndexOutOfBoundsExceptionが発生します。
クラスについて詳しく知りたい方へ
クラスについては変数やメソッドを呼び出す方法や、クラスを継承する方法などのいろいろな使い方があります。
クラス中の変数やメソッドを呼び出す方法
クラスの中の変数やメソッドを呼び出す方法については次の記事にまとめているので、ぜひ確認してください!
クラスを継承する方法
クラスを継承する方法については次の記事にまとめているので、ぜひ確認してください!
メソッドについて詳しく知りたい方へ
この記事では紹介しきれなかったメソッドのいろいろな使い方を次の記事にまとめているので、ぜひ確認してください!
まとめ
この記事では、クラス名とメソッド名を取得する方法について解説しました。
スタックトレースを理解するとデバッグに役立つのでぜひ覚えてください。
もし、クラス名とメソッド名を取得する方法を忘れてしまったら、この記事を思い出してくださいね!