使用 StringBuilder 拼接日志需预估容量、分段追加、避免中间 toString()、统一换行符、控制对象打印深度、过滤敏感字段,并配合日志级别开关使用。

直接用 StringBuilder 拼接多行日志和调试信息,核心是避免字符串不可变带来的重复创建对象开销,同时合理预估容量、分段追加、适时转成字符串输出。
预分配足够容量,减少扩容次数
每次 append() 超出当前容量时,StringBuilder 会自动扩容(通常是翻倍),频繁扩容影响性能。调试信息往往结构固定,可粗略估算总长度。
- 例如拼接 10 行日志,每行平均 80 字符,预留 1000 字符:
new StringBuilder(1000) - 若含变量(如
id=123、name="user"),把已知固定文本长度 + 变量最大可能长度(如数字最多 10 位、字符串取典型长度)加总 - 不确定时宁可略大,不建议用默认构造(初始 16 容量)直接拼几十行
按逻辑分块 append,别反复 toString()
调试信息常含时间戳、方法名、参数、异常堆栈等不同来源内容。应一次性构建完再转字符串,避免中间多次 toString() —— 那会生成新 String 对象,失去 StringBuilder 的意义。
- 正确:
sb.append("[").append(LocalDateTime.now()).append("] "); sb.append("method: ").append(methodName); ... return sb.toString(); - 错误:
log(sb.toString()); sb.append("..."); log(sb.toString());—— 多余创建字符串,还可能漏掉后半部分 - 多行换行统一用
System.lineSeparator(),兼容 Windows/Linux/Mac
嵌套对象或集合要控制深度,避免无限递归
调试时常用 sb.append(obj) 打印对象,但若对象重写了 toString() 且内部引用自身(如循环依赖的 DTO),会导致 StackOverflowError 或巨长字符串。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 对复杂对象,优先调用专门的调试工具方法,如
Objects.toString(obj, "null")或自定义简版debugToString() - 打印集合时限制元素数量:
list.subList(0, Math.min(5, list.size())),避免日志刷屏 - 敏感字段(密码、token)主动过滤,不要依赖
toString()默认行为
结合日志框架使用,别替代 logger
StringBuilder 是拼接工具,不是日志门面。生产环境仍应通过 SLF4J / Log4j 等输出,仅在需要精细控制格式(如组装带缩进的 JSON 调试块)时前置构建。
- 推荐模式:
if (log.isDebugEnabled()) { StringBuilder sb = new StringBuilder(512); sb.append(...); log.debug(sb.toString()); } - 避免在
log.info("msg: {}", sb.toString())中提前 toString() —— 即使日志级别关闭,也白做了拼接 - 调试阶段可封装为工具方法,如
DebugLogBuilder.start().add("user", user).add("req", req).build(),提升复用性
不复杂但容易忽略:容量预估、一次成型、安全截断、配合日志开关——这四点做好,StringBuilder 就能稳稳扛住高频调试输出。

















