java中不能直接new logger,因其构造方法为protected,须通过logger.getlogger()获取实例;jul配置繁琐性能一般,推荐slf4j+logback组合,解耦api与实现,支持灵活配置和高性能日志输出。

Java里没有叫 Logger 的“类”可以直接 new 出来用——它是个抽象基类,实际要用的是具体实现,比如 java.util.logging.Logger(JUL)或 SLF4J + Logback / Log4j2 等组合。
为什么直接 new Logger 会报错
因为 java.util.logging.Logger 的构造方法是 protected,不能直接实例化;必须通过静态工厂方法获取:
-
Logger.getLogger("my.logger.name")—— 返回单例 Logger 实例 - 名字相同就返回同一个对象,不重复创建
- 名字带点号(如
"com.example.service.UserService")会自动形成层级,影响日志级别继承
java.util.logging(JUL)的典型用法
JUL 是 JDK 自带的日志 API,开箱即用但配置麻烦、性能一般,适合简单场景:
- 默认只输出
INFO及以上级别到控制台,WARNING和SEVERE会带堆栈 - 要输出
DEBUG或TRACE,得手动调logger.setLevel(Level.FINE)并给 Handler 设置对应级别 - 格式固定,想自定义输出(比如加时间戳、线程名)得写
Formatter子类 - 配置通常靠
logging.properties文件,路径需通过-Djava.util.logging.config.file=xxx指定
更推荐的方案:SLF4J + Logback
这是当前 Java 生态最主流的日志组合,解耦 API 与实现,灵活且性能好:
立即学习“Java免费学习笔记(深入)”;
- 写代码只依赖
org.slf4j.Logger和LoggerFactory,不绑定具体实现 - 引入
logback-classic就自动生效,无需额外绑定代码 -
logback.xml支持按包设置级别、滚动文件、异步输出、JSON 格式等 - 注意避免 classpath 下存在多个 binding(如同时有
logback-classic和log4j-slf4j-impl),否则 SLF4J 会报Multiple bindings警告
常见错误和坑
很多问题不是 API 不会用,而是环境或依赖没理清:
- 用
slf4j-api却没加实现(如logback-classic),运行时报Failed to load class "org.slf4j.impl.StaticLoggerBinder" - Maven 里排除了传递依赖的旧版
slf4j-log4j12,但忘了排除其依赖的log4j,导致NoClassDefFoundError: org/apache/log4j/Logger - 在 Lambda 表达式里写
logger.debug("value={}", obj.toString())—— 即使日志被禁用,toString()仍会执行,应改用logger.debug("value={}", () -> obj.toString())(支持 Supplier 的版本) - JUL 和 SLF4J 共存时,想把 JUL 日志桥接到 SLF4J,得加
jul-to-slf4j,并调SLF4JBridgeHandler.install(),否则 JUL 的日志会漏掉
真正麻烦的从来不是“怎么打一行日志”,而是让所有组件(框架、第三方库、自研模块)的日志统一输出、可控、不冲突。别只盯着 logger.info() 怎么写,先确认 classpath 里到底有几个日志实现、它们之间有没有桥接、配置文件加载路径对不对。










