Common 常用模块

Date 日期处理

Reflection 反射

Input/Output 输入/输出

加密/解密

其他

StrUtil

StrUtil 当前提供简单模板替换以及数组、列表拼接;不再提供填充、字符计数或成员判断方法。

模板

Map 重载替换 ${name} 占位符,Map 中缺失或为 null 的值替换为空字符串。

Map<String, Object> values = new HashMap<>();
values.put("name", "Ada");
String message = StrUtil.simpleTpl("Hello, ${name}! ${missing}", values);
// Hello, Ada!

JavaBean 重载替换可读属性对应的 #{property} 占位符。Bean 属性为 null 时替换为文本 null,只写属性会跳过。替换值按字面量处理,$ 和反斜杠可安全使用。getter 执行失败时,抛出的 RuntimeException 会标明属性名并保留原始异常作为 cause。

String message = StrUtil.simpleTpl("Hello, #{name}!", user);

拼接数组和列表

String array = StrUtil.join(new String[]{"a", null, "c"}, "&");
String list = StrUtil.join(Arrays.asList("a", "b", "c"), "[%s]", ", ");
// a&&c
// [a], [b], [c]

可用重载包括泛型数组、带格式模板的字符串数组,以及带可选模板的字符串列表。null 元素会输出为空字符串。

占位符和格式规则

两类模板重载刻意使用不同的占位符语法:

重载 占位符 缺失/null 值
simpleTpl(String, Map) ${word} 空字符串
simpleTpl(String, Object) #{property} 可读属性为 null 时输出文本 null

Map 占位符仅匹配单词字符(${name_1} 有效,${user.name} 不属于该 API 的占位符)。无法识别的文本保持不变。Bean 重载检查 JavaBean getter 属性(包含继承属性),不直接读取字段。

Map<String, Object> values = new HashMap<>();
values.put("path", "$1\\temp");
String result = StrUtil.simpleTpl("path=${path}", values);
// path=$1\temp

之所以能够安全处理 $1,是因为替换内容在调用 Matcher.appendReplacement 前会被引用;$1 只是数据,不是正则反向引用。列表拼接的模板会传入 String.format,因此应包含如 %s 的合适转换符。

选择合适的工具

StrUtil 专注于小型格式化操作。正则替换使用 RegExpHelper;URL/表单编码使用 UrlCodec;字节、字符集和十六进制转换使用 StringBytes。

实现原理与取舍

Map 模板重载使用一个预编译 Pattern 扫描 ${word},再通过 Matcher.appendReplacement / appendTail 构造结果。对替换文本进行引用后,正则引擎不会把值中的 $ 或反斜杠解释为特殊语法。Bean 重载则使用 JavaBeans 内省,并针对每个可读属性调用普通 String.replace;这也解释了它为何使用 #{property} 语法,以及为什么 null 行为不同。

拼接方法使用 StringBuilder,仅在元素之间附加分隔符,从而避免尾部分隔符。它们刻意不转义值、也不进行依赖 Locale 的格式化;需要时应在拼接前完成这些转换。