在日誌記錄、除錯追蹤等場景中,常需要自動獲取「當前執行的方法名、所在檔案、行號」等上下文資訊。Java 沒有像 C/C++ 的 __FILE__、__LINE__ 預處理器巨集,但可透過 StackTraceElement 輕鬆實現同等功能。
封裝一個 CommonFunction 工具類,提供靜態方法供全專案呼叫:
package com.example.util;
import java.text.SimpleDateFormat;
import java.util.Date;
public abstract class CommonFunction {
/**
* 獲取完整呼叫位置資訊:[檔案名 | 行號 | 方法名]
*/
public static String getFileLineMethod() {
StackTraceElement trace = new Exception().getStackTrace()[1];
return String.format("[%s | %d | %s]",
trace.getFileName(), trace.getLineNumber(), trace.getMethodName());
}
/** 獲取當前檔案名 */
public static String _FILE_() {
return new Exception().getStackTrace()[1].getFileName();
}
/** 獲取當前方法名 */
public static String _FUNC_() {
return new Exception().getStackTrace()[1].getMethodName();
}
/** 獲取當前行號 */
public static int _LINE_() {
return new Exception().getStackTrace()[1].getLineNumber();
}
/** 獲取當前時間戳 (yyyy-MM-dd HH:mm:ss.SSS) */
public static String _TIME_() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date());
}
}
new Exception().getStackTrace() 會返回當前執行緒的堆疊追蹤陣列:
[0] 是當前方法(即 getFileLineMethod 自身)[1] 是**呼叫者**的方法,這才是我們真正想要的資訊建立 Exception 物件並擷取堆疊追蹤有固定開銷,建議:
public class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
public void createOrder(OrderDTO dto) {
// 自動帶入呼叫位置,無需手動硬編碼
log.debug("{} 開始建立訂單:{}", CommonFunction.getFileLineMethod(), dto.getOrderNo());
// 業務邏輯...
log.info("{} 訂單建立完成", CommonFunction._FUNC_());
}
}
若使用 Logback/Log4j2,可直接在 PatternLayout 中使用 %class、%method、%line 等轉換字元,無需手工包裝,效能更佳:
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %class.%method\(%line\) - %msg%n</pattern>
透過 StackTraceElement 實現類 C 的 __FILE__/__LINE__ 功能,代碼簡潔且無外部依賴。但在高效能場景下,優先考慮日誌框架內建的位置資訊輸出。