java获取当前类的类名和方法名

     阅读:40

如果我们想要获取当前类的类名,那么可以使用如下代码:

String className = this.getClass().getName();// 这是完整的类路径名
String simpleClassName = this.getClass().getSimpleName();// 仅仅是类名

如果我们想要在某个方法内获取到该方法的方法名,可以使用如下代码:

String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();

完整代码如下:

package com.hello.demo;

public class TestA {
    public void hello() {
        System.out.println("hello world");
        String className = this.getClass().getName();
        String simpleClassName = this.getClass().getSimpleName();
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        // hello world
        //className: com.hello.demo.TestA, simpleClassName: TestA, methodName: hello
        System.out.println("className: " + className + ", simpleClassName: " + simpleClassName + ", methodName: " + methodName);
    }

    public static void main(String[] args) {
        new TestA().hello();
    }
}

获取类名很容易理解,而获取到方法名是跟运行栈的结构层次有关系。我们尝试直接打印Thread.currentThread().getStackTrace()数组中的所有值:

package com.hello.demo;

public class TestA {
    public void hello() {
        for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
            System.out.println(element);
        }
    }

    public static void main(String[] args) {
        new TestA().hello();
    }
}
/*
    java.lang.Thread.getStackTrace(Thread.java:1559)
    com.hello.demo.TestA.hello(TestA.java:5)
    com.hello.demo.TestA.main(TestA.java:11)
 */

可以发现数组中第二个元素(下标为1)正是com.hello.demo.TestA.hello,所以我们可以得到运行的类名是TestA和方法名hello。所以我们能够根据调用栈来获取到方法的方法名信息。注意StackTraceElement有几个方法:

  • getClassName():获取类名。
  • getLineNumber():获取行号。
  • getMethodName():获取方法名。
  • getFileName():获取文件名。

拓展:既然我们可以通过调用栈来获取到类名和方法名,那么我们就可以利用这一点来打印更加精确的日志,如某个类的具体某方法的日志。上面的代码只能获取到方法所在类的类名和方法本身的方法名,打印日志的话我们更希望获取到调用了这个方法的类名和调用了这个方法的方法名。如下:

TestB.java:该类中有一个方法等待被调用。

package com.hello.demo;

public class TestB {
    public void world() {
        System.out.println("hello world");
    }
}

TestA.java:我们在TestA类中也有一个hello方法,在该方法内调用了TestB类的world方法,我们希望world方法能够打印hello方法所在类的类名和hello这个方法名

package com.hello.demo;

public class TestA {
    public void hello() {
        new TestB().world();
    }

    public static void main(String[] args) {
        new TestA().hello();
    }
}

如果按照上面的方式,则只会获取到world方法所在类的类名和方法名。

package com.hello.demo;

public class TestB {
    public void world() {
        System.out.println("hello world");
        String className = this.getClass().getName();
        String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();
        // className: com.hello.demo.TestB, methodName: world
        System.out.println("className: " + className + ", methodName: " + methodName);
    }
}

如果想要获取到调用world方法的所在类类名和方法名,就必须往调用栈的上一层找,如下:

package com.hello.demo;

public class TestB {
    public void world() {
        for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
            String className = element.getClassName();
            String methodName = element.getMethodName();
            System.out.println("className: " + className + ", methodName: " + methodName);
        }
    }
}
/*
    className: java.lang.Thread, methodName: getStackTrace
    className: com.hello.demo.TestB, methodName: world
    className: com.hello.demo.TestA, methodName: hello
    className: com.hello.demo.TestA, methodName: main
 */

栈是先进后出,所以从上往下是数组中的第三个元素(下标为2)。即:

String className = Thread.currentThread().getStackTrace()[2].getClassName();
String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();