• Java代码中如何获文件名和行号等源码信息?


    C语言中有__FILE__、__LINE__等预定义宏,用于获取当前文件名和行号等信息,而且它们的值在预处理时就已经确定了,不会占用运行时时间去计算,这对打印日志相当有用。那么,Java语言是否也有类似的功能呢?

    Java是否提供某种方法:可以让用户代码在编译时确定源码行号等信息,本人暂时不知晓。不过从网上搜索得到的方法大致是:

    • Thread.currentThread().getStackTrace()[1].getFileName():获取当前文件名;
    • Thread.currentThread().getStackTrace()[1].getLineNumber():获取当前行号。

    其中:Thread.currentThread().getStackTrace()返回的是一个数组形式的函数调用栈(栈顶在索引0处),其中第1个元素(索引为0)为最新调用的函数信息(getStackTrace()),第2个元素(索引为1)为当前函数(即调用getStackTrace()的函数)信息。示例:

     1 public class Test {
     2     public static void main(String args[]) {
     3         StackTraceElement[] stack = Thread.currentThread().getStackTrace();
     4         for (int i = 0; i < stack.length; ++i)
     5             System.out.println(stack[i].getFileName() + ":" + stack[i].getLineNumber() + ": " + stack[i].getMethodName());
     6         System.out.println("");
     7         foo();
     8     }
     9     static void foo() {
    10         StackTraceElement[] stack = Thread.currentThread().getStackTrace();
    11         for (int i = 0; i < stack.length; ++i)
    12             System.out.println(stack[i].getFileName() + ":" + stack[i].getLineNumber() + ": " + stack[i].getMethodName());
    13         System.out.println("");
    14         bar();
    15     }
    16     static void bar() {
    17         StackTraceElement[] stack = Thread.currentThread().getStackTrace();
    18         for (int i = 0; i < stack.length; ++i)
    19             System.out.println(stack[i].getFileName() + ":" + stack[i].getLineNumber() + ": " + stack[i].getMethodName());
    20     }
    21 }

    输出:

    $ javac Test.java
    $ java Test
    null:-1: getStackTrace
    Test.java:3: main
    
    null:-1: getStackTrace
    Test.java:10: foo
    Test.java:7: main
    
    null:-1: getStackTrace
    Test.java:17: bar
    Test.java:14: foo
    Test.java:7: main

    于是,如果我们想在日志中打印当前文件名和行号,就可以:

     1 public class Test {
     2     public static void main(String args[]) {
     3         System.out.println(Thread.currentThread().getStackTrace()[1].getFileName() + ":" + Thread.currentThread().getStackTrace()[1].getLineNumber());
     4         foo();
     5     }
     6     static void foo() {
     7         System.out.println(Thread.currentThread().getStackTrace()[1].getFileName() + ":" + Thread.currentThread().getStackTrace()[1].getLineNumber());
     8         bar();
     9     }
    10     static void bar() {
    11         System.out.println(Thread.currentThread().getStackTrace()[1].getFileName() + ":" + Thread.currentThread().getStackTrace()[1].getLineNumber());
    12     }
    13 }

    输出:

    $ javac Test.java
    $ java Test
    Test.java:3
    Test.java:7
    Test.java:11

    不过每次都要写这么长的几串代码“Thread.currentThread().getStackTrace()[1].getXXX()”拼一起看起来难看敲起来也累。于是我们可以将getStackTrace()封装到另一个函数中:

     1 public class Test {
     2     public static void main(String args[]) {
     3         System.out.println(__FILE__() + ":" + __LINE__());
     4         foo();
     5     }
     6     static void foo() {
     7         System.out.println(__FILE__() + ":" + __LINE__());
     8         bar();
     9     }
    10     static void bar() {
    11         System.out.println(__FILE__() + ":" + __LINE__());
    12     }
    13     static String __FILE__() {
    14         return Thread.currentThread().getStackTrace()[2].getFileName();
    15     }
    16     static int __LINE__() {
    17         return Thread.currentThread().getStackTrace()[2].getLineNumber();
    18     }
    19 }

    输出结果一样:

    $ javac Test.java
    $ java Test
    Test.java:3
    Test.java:7
    Test.java:11

    参考:

    1. http://stackoverflow.com/questions/22677815/eclipse-println-line-does-such-a-preprocessor-macro-exist-to-program
    2. http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#getStackTrace--
    3. http://docs.oracle.com/javase/8/docs/api/java/lang/StackTraceElement.html
    4. http://stackoverflow.com/questions/115008/how-can-we-print-line-numbers-to-the-log-in-java
    5. http://www.codeceo.com/article/8-java-log-framework.html
  • 相关阅读:
    线段树时间分治
    CDQ分治
    并查集练习
    hihocoder 1513 小Hi的烦恼 (bitset优化)
    线段树维护哈希
    使用swift语言进行IOS应用开发
    用jquery+Asp.Net实现省市二级联动
    苹果IOS与谷歌 android系统的UI设计原则
    优秀设计师应当知道的20大UI设计原则
    JQuery Easy Ui dataGrid 数据表格
  • 原文地址:https://www.cnblogs.com/itwhite/p/5052886.html
Copyright © 2020-2023  润新知