获取方法名,通用
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))+")";
}
}