獲取方法名,通用
Thread.currentThread().getStackTrace()[1].getClassName()
非靜態方法獲取方法名
this.getClass().getName()
獲取類名
Thread.currentThread().getStackTrace()[1].getMethodName()
那麼接下來如果每次都要這麼用寫那麼多太累,所以封裝嘛,封裝可以幫助更好的理解
stackTraceElement[] 存放了一些 stackTraceElement,而StackTraceElement表示StackTrace(堆棧軌跡)中的一個方法對象,屬性包括方法的類名、方法名、文件名以及調用的行數。
Thread.currentThread()獲取系統當前運行的線程,getStackTrace()可以獲取java線程運行棧的信息。
一個線程運行棧的信息如下:首先棧是先進後出的,
入口類 StringTest 中 main() 方法,入棧
public class StringTest { public static void main(String[] args) { Test.me().print(); } }
緊接着 調用 Test類 me(), 入棧 隨後 調用 print() 入棧
public class Test{ public static Test me () { System.out.println(LogUtil.getLog()); return new Test(); } public void print () { System.out.println(LogUtil.getLog()); System.out.println("this is Test"); } }
調用 LogUtil log() ,入棧,實際打印出來的時候是沒有className()和methodName()的,如果在className和methodName中stackTraceElement下標爲2 會發現打印的是getLog,這也對應了下方的註釋數據,也就是實際還有一層,getLog調用className和methodName會在getLog調用之後 入棧。
最終是我們調用的getStackTrace() 入棧。
遵從先進後出的順序,我們從上到下下標依次從 0-n ,不難發現調用層數決定下標值,進一步理解java StackTraceElement對象
public class LogUtil { private static final String LOG_LEVEL = StringUtil.isBlank(Globals.LOG_LEVEL) ? Globals.DEFAULT_LOG_LEVEL : Globals.LOG_LEVEL; //默認LOG級別 public static LogUtil me() { return new LogUtil(); } public void log(Object log) { System.out.print("["+LOG_LEVEL+" ] "+getLog(2)); System.out.println("\t"+String.valueOf(log == null ? "" : log)); } private static String className(int i) { return Thread.currentThread().getStackTrace()[++i].getClassName(); } private static String methodName(int i) { return Thread.currentThread().getStackTrace()[++i].getMethodName(); } private static int lineNumber(int i) { return Thread.currentThread().getStackTrace()[++i].getLineNumber();} /** * * @return */ public static String getLog() { return DateUtil.getNow()+"\t==>\t"+className(2)+":"+methodName(2); } public static String getLog(int i) { return DateUtil.getNow()+"\t==>\t"+className((i+1))+":("+methodName((i+1))+"."+lineNumber((i+1))+")"; } }