Java日志:如何用Lambda表达式替换匿名内部类设置Handler的Formatter
用Lambda表达式替换java.util.logging.Formatter的匿名内部类方案
嘿,这个问题我太清楚啦!其实关键在于搞懂java.util.logging.Formatter的本质——它是一个函数式接口,因为它只有一个必须实现的抽象方法:String format(LogRecord record)。这就意味着我们完全可以用Lambda表达式直接替代原来的匿名内部类写法。
先看你的原有可运行代码(大概是这样)
import java.util.logging.ConsoleHandler; import java.util.logging.Formatter; import java.util.logging.LogRecord; import java.util.logging.Logger; public class LoggerDemo { public static void main(String[] args) { Logger logger = Logger.getLogger(LoggerDemo.class.getName()); ConsoleHandler handler = new ConsoleHandler(); // 你现在用的匿名内部类写法 handler.setFormatter(new Formatter() { @Override public String format(LogRecord record) { return String.format("[%s] %s%n", record.getLevel(), record.getMessage()); } }); logger.addHandler(handler); logger.info("这是一条测试日志"); } }
替换成Lambda表达式的写法
直接把匿名内部类换成匹配format方法签名的Lambda就行,一行搞定:
handler.setFormatter(record -> String.format("[%s] %s%n", record.getLevel(), record.getMessage()));
如果日志格式逻辑复杂,多行Lambda也没问题
要是你需要处理更多日志字段(比如时间戳、类名),可以用带大括号的Lambda来写多行逻辑:
handler.setFormatter(record -> { // 自定义复杂格式逻辑 String logLevel = record.getLevel().getLocalizedName(); String logMsg = record.getMessage(); long timestamp = record.getMillis(); String className = record.getSourceClassName(); return String.format("[%tF %tT] [%s] [%s] %s%n", timestamp, timestamp, logLevel, className, logMsg); });
为什么能这么用?
因为Java 8及以后,只要一个接口只有一个抽象方法(不管它有多少默认方法/静态方法),就属于函数式接口,就能用Lambda表达式实现。Formatter正好符合这个条件——它的format方法是唯一的抽象方法,其他方法比如getHead、getTail都有默认的空实现,完全不影响Lambda的使用。
内容的提问来源于stack exchange,提问作者Joop Jansen
相关产品推荐
相关产品推荐

