Apache Commons Lang 3.21.0 常用 API 与工具类详解
详解 Apache Commons Lang 3.21.0 四大常用工具类 StringUtils、BooleanUtils、ArrayUtils、ObjectUtils,逐项实测 null 安全约定与真实返回值,含废弃 API 提示与替代写法。
Apache Commons Lang 3.21.0 常用 API 与工具类详解
目标:逐一实测 Apache Commons Lang 3.21.0 最常用的四个工具类——
StringUtils、BooleanUtils、ArrayUtils、ObjectUtils,用真实回显固定它们的 null 安全约定与边界行为,并标注 3.21.0 中已废弃的方法与替代写法。以下全部命令与输出均已在 Ubuntu 22.04(x86_64)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04.5 LTS(x86_64)
- JDK:OpenJDK 17.0.20.1
- 构建工具:Apache Maven 3.6.3
- 目标库:org.apache.commons:commons-lang3:3.21.0(2026-09-29 发布,零传递依赖,最低 Java 8)
- 示例工程目录:/opt/lang-demo(安装过程见《Ubuntu 22.04 安装 Apache Commons Lang 指南》)
- 统一运行方式:
cd /opt/lang-demo
CP=target/classes:/root/.m2/repository/org/apache/commons/commons-lang3/3.21.0/commons-lang3-3.21.0.jar
java -Dfile.encoding=UTF-8 -cp $CP demo.<DemoClass>
说明:
-Dfile.encoding=UTF-8用于规避 POSIX locale 下中文输出变问号的问题(排障实录见《Ubuntu 22.04 安装 Apache Commons Lang 指南》FAQ Q3)。本文示例类所在的实测工程共含 6 个演示类(本系列多篇文档同源),读者按本文只创建 3 个类时,编译输出的文件数不同属正常。
二、工具类总览
四个工具类的定位与包位置(均在 org.apache.commons.lang3 顶层,无需进子包):
| 工具类 | 定位 | 本文覆盖的高频方法 |
|---|---|---|
| StringUtils | null 安全的字符串操作全集 | isEmpty、isBlank、join、split、abbreviate、substringBetween、overlay、left、right、mid、capitalize、defaultString |
| BooleanUtils | Boolean 装箱与字符串/整数的布尔转换 | toBoolean、toInteger、isTrue、negate |
| ArrayUtils | 数组增删截查(int[]/String[] 等各类型重载) | add、remove、subarray、isEmpty、indexOf、contains |
| ObjectUtils | 对象判空与默认值 | defaultIfNull(已废弃)、getIfNull、firstNonNull、allNull、anyNull |
前置依赖只有一个坐标:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.21.0</version>
</dependency>
三、前置条件:工程与依赖确认
沿用《Ubuntu 22.04 安装 Apache Commons Lang 指南》的 Maven 工程(pom 中 commons-lang3 3.21.0 + project.build.sourceEncoding=UTF-8 + maven-compiler-plugin 3.11.0 带 -Xlint:deprecation)。先确认依赖解析正常:
cd /opt/lang-demo && mvn -B dependency:tree
输出节选(实测):
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ lang-demo ---
[INFO] demo:lang-demo:jar:1.0.0
[INFO] \- org.apache.commons:commons-lang3:jar:3.21.0:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
依赖树只有 commons-lang3 自身(零传递依赖)。本文新增的演示类放入 src/main/java/demo/ 后统一编译:
cd /opt/lang-demo && mvn -B compile
输出节选(实测,compile 段与结尾;仅保留与本文四类相关的 WARNING):
[INFO] Compiling 6 source files with javac [debug release 17] to target/classes
[WARNING] /opt/lang-demo/src/main/java/demo/StringUtilsDemo.java:[54,75] defaultString(java.lang.String,java.lang.String) in org.apache.commons.lang3.StringUtils has been deprecated
[WARNING] /opt/lang-demo/src/main/java/demo/ExceptionSystemDemo.java:[37,75] <T>defaultIfNull(T,T) in org.apache.commons.lang3.ObjectUtils has been deprecated
[WARNING] /opt/lang-demo/src/main/java/demo/ExceptionSystemDemo.java:[52,46] getValue() in org.apache.commons.lang3.mutable.MutableInt has been deprecated
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] Total time: 1.318 s
说明:输出末行之后还有
Finished at与分隔线(下同,不再重复展示)。三条 WARNING 提示本文会讲到的废弃点:StringUtils.defaultString(String,String)与ObjectUtils.defaultIfNull已 @Deprecated(MutableInt属进阶篇内容,见《Apache Commons Lang 3.21.0 进阶 API 与废弃迁移详解》),功能不受影响,替代写法在对应小节给出。
四、StringUtils 详解
StringUtils 的核心设计是 null 安全:传入 null 不抛 NPE,返回确定的值。本节用一个完整演示类逐项实测,所有输出为真实回显。
4.1 判空约定:isEmpty 与 isBlank
源码 /opt/lang-demo/src/main/java/demo/StringUtilsDemo.java(完整,后续小节的方法都在这个类里):
package demo;
import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
public class StringUtilsDemo {
public static void main(String[] args) {
System.out.println("== null 安全约定 ==");
System.out.println("isEmpty(null) = " + StringUtils.isEmpty(null));
System.out.println("isEmpty(\"\") = " + StringUtils.isEmpty(""));
System.out.println("isEmpty(\" \") = " + StringUtils.isEmpty(" "));
System.out.println("isBlank(null) = " + StringUtils.isBlank(null));
System.out.println("isBlank(\"\") = " + StringUtils.isBlank(""));
System.out.println("isBlank(\" \") = " + StringUtils.isBlank(" "));
System.out.println("isNotBlank(\" a \") = " + StringUtils.isNotBlank(" a "));
System.out.println("== join ==");
System.out.println("join([a,b,c], '-') = " + StringUtils.join(new String[]{"a", "b", "c"}, '-'));
System.out.println("join([1,2,3], ',') = " + StringUtils.join(new int[]{1, 2, 3}, ','));
System.out.println("== split ==");
String[] parts = StringUtils.split("a,b,,c", ',');
System.out.println("split(\"a,b,,c\", ',') = " + Arrays.toString(parts));
System.out.println("split(null, ',') = " + Arrays.toString(StringUtils.split(null, ',')));
System.out.println("splitPreserveAllTokens(\"a,b,,c\", ',') = " + Arrays.toString(StringUtils.splitPreserveAllTokens("a,b,,c", ',')));
System.out.println("== abbreviate ==");
System.out.println("abbreviate(\"abcdefg\", 10) = " + StringUtils.abbreviate("abcdefg", 10));
System.out.println("abbreviate(\"abcdefg\", 6) = " + StringUtils.abbreviate("abcdefg", 6));
try {
StringUtils.abbreviate("abcdefg", 3);
} catch (IllegalArgumentException e) {
System.out.println("abbreviate(\"abcdefg\", 3) 抛出 IllegalArgumentException: " + e.getMessage());
}
System.out.println("== substringBetween ==");
System.out.println("substringBetween(\"<a>text</a>\", \"<a>\", \"</a>\") = " + StringUtils.substringBetween("<a>text</a>", "<a>", "</a>"));
System.out.println("== overlay ==");
System.out.println("overlay(\"abcdef\", \"***\", 2, 5) = " + StringUtils.overlay("abcdef", "***", 2, 5));
System.out.println("== left / right / mid ==");
System.out.println("left(\"abcdef\", 3) = " + StringUtils.left("abcdef", 3));
System.out.println("right(\"abcdef\", 3) = " + StringUtils.right("abcdef", 3));
System.out.println("mid(\"abcdef\", 2, 3) = " + StringUtils.mid("abcdef", 2, 3));
System.out.println("left(null, 3) = " + StringUtils.left(null, 3));
System.out.println("right(\"abc\", 10) = " + StringUtils.right("abc", 10));
System.out.println("== capitalize / defaultString ==");
System.out.println("capitalize(\"hello\") = " + StringUtils.capitalize("hello"));
System.out.println("capitalize(null) = " + StringUtils.capitalize(null));
System.out.println("defaultString(null) = [" + StringUtils.defaultString(null) + "]");
System.out.println("defaultString(null, \"N/A\") = " + StringUtils.defaultString(null, "N/A"));
}
}
判空部分的真实回显:
== null 安全约定 ==
isEmpty(null) = true
isEmpty("") = true
isEmpty(" ") = false
isBlank(null) = true
isBlank("") = true
isBlank(" ") = true
isNotBlank(" a ") = true
要点:
isEmpty只认 null 与空串,纯空格" "返回 false;isBlank把纯空白也视为空。- null 安全:
isEmpty(null)、isBlank(null)直接返回 boolean,不抛 NPE——这正是与str.isEmpty()手写判空的核心差异。
4.2 拼接与拆分:join 与 split
同上类的真实回显:
== join ==
join([a,b,c], '-') = a-b-c
join([1,2,3], ',') = 1,2,3
== split ==
split("a,b,,c", ',') = [a, b, c]
split(null, ',') = null
splitPreserveAllTokens("a,b,,c", ',') = [a, b, , c]
要点:
join支持 String[] 与基本类型数组(int[] 等)两类重载。split丢弃空 token:a,b,,c只得到 3 个元素;要保留空位用splitPreserveAllTokens(得到 4 个)。split(null, ',')返回 null 而不是抛异常。
4.3 缩写、提取与覆盖:abbreviate、substringBetween、overlay
同上类的真实回显:
== abbreviate ==
abbreviate("abcdefg", 10) = abcdefg
abbreviate("abcdefg", 6) = abc...
abbreviate("abcdefg", 3) 抛出 IllegalArgumentException: Minimum abbreviation width is 4
== substringBetween ==
substringBetween("<a>text</a>", "<a>", "</a>") = text
== overlay ==
overlay("abcdef", "***", 2, 5) = ab***f
要点:
abbreviate的省略号占 3 个字符,最小可用宽度是 4,传入 3 直接抛IllegalArgumentException(实测报错文案如上),不会被静默处理。substringBetween提取两个定界符之间的内容,取不到时返回 null。overlay(start, end)是「左闭右开」区间替换:2 到 5 的字符被***替换。
4.4 取子串三件套:left、right、mid
同上类的真实回显:
== left / right / mid ==
left("abcdef", 3) = abc
right("abcdef", 3) = def
mid("abcdef", 2, 3) = cde
left(null, 3) = null
right("abc", 10) = abc
要点:
left/right/mid全部 null 安全:null 进 null 出。- 请求长度超过串长时截到串尾(
right("abc", 10) = abc),不抛异常。 mid(str, pos, len)从 pos(0 起)开始取 len 个字符。
4.5 首字母大写与默认值:capitalize、defaultString
同上类的真实回显:
== capitalize / defaultString ==
capitalize("hello") = Hello
capitalize(null) = null
defaultString(null) = []
defaultString(null, "N/A") = N/A
要点:
capitalize只把首字母大写,null 直接返回 null。defaultString(null)返回空串"";defaultString(null, "N/A")返回自定义默认值。- 废弃提示:双参重载
defaultString(String,String)在 3.21.0 已 @Deprecated(4.x 编译实测见第三章 WARNING),单参重载未废弃。替代写法:不需要自定义默认值时用单参defaultString(str),需要时用三元表达式str == null ? "N/A" : str或Objects.toString(str, "N/A")。
💡 技术拓展:StringUtils 与 Guava 字符串工具的设计差异——
维度 Commons StringUtils Guava(Strings/Joiner/Splitter) null 语义 方法级 null 安全:null 进、约定值出(isEmpty(null)=true) 多数方法 Preconditions 前置断言:null 直接抛 NullPointerException 空白判定 isEmpty / isBlank 两档 Strings.isNullOrEmpty 一档(无空白判定,需自行 trim) 拆分 split(丢空 token) Splitter 链式配置(omitEmptyStrings/trimResults 可选) 拼接 join(数组, 分隔符) Joiner 链式(skipNulls、useForNull 可选) 适用判断 「宽容处理脏数据」的防御式风格 「快速失败暴露问题」的契约式风格 选型口径:解析外部输入(日志、表单、报文)优先 StringUtils 的 null 安全;内部模块边界想尽早暴露传参 bug 用 Guava 的断言风格。两者可在同一工程共存(同 classpath 验证见《Apache Commons Lang 3.21.0 快速入门与集成示例》)。
五、BooleanUtils 详解
BooleanUtils 处理 Boolean 装箱类型与字符串/整数之间的转换,全部方法 null 安全。源码 /opt/lang-demo/src/main/java/demo/BooleanArrayDemo.java(完整,ArrayUtils 部分见第六章):
package demo;
import java.util.Arrays;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
public class BooleanArrayDemo {
public static void main(String[] args) {
System.out.println("== BooleanUtils ==");
System.out.println("toBoolean(\"yes\") = " + BooleanUtils.toBoolean("yes"));
System.out.println("toBoolean(\"y\") = " + BooleanUtils.toBoolean("y"));
System.out.println("toBoolean(\"on\") = " + BooleanUtils.toBoolean("on"));
System.out.println("toBoolean(\"true\") = " + BooleanUtils.toBoolean("true"));
System.out.println("toBoolean(\"1\") = " + BooleanUtils.toBoolean("1"));
System.out.println("toBoolean(\"no\") = " + BooleanUtils.toBoolean("no"));
System.out.println("toBoolean(null) = " + BooleanUtils.toBoolean((String) null));
System.out.println("toBoolean(1) = " + BooleanUtils.toBoolean(1));
System.out.println("toBoolean(0) = " + BooleanUtils.toBoolean(0));
System.out.println("toInteger(true, 1, 0, -1) = " + BooleanUtils.toInteger(true, 1, 0, -1));
System.out.println("isTrue(Boolean.TRUE) = " + BooleanUtils.isTrue(Boolean.TRUE));
System.out.println("isTrue(null) = " + BooleanUtils.isTrue(null));
System.out.println("negate(Boolean.TRUE) = " + BooleanUtils.negate(Boolean.TRUE));
System.out.println("negate(null) = " + BooleanUtils.negate(null));
System.out.println("== ArrayUtils ==");
int[] arr = {1, 2, 3};
int[] added = ArrayUtils.add(arr, 4);
System.out.println("add([1,2,3], 4) = " + Arrays.toString(added));
System.out.println("remove([1,2,3,4], 1) = " + Arrays.toString(ArrayUtils.remove(added, 1)));
System.out.println("subarray([1,2,3,4], 1, 3) = " + Arrays.toString(ArrayUtils.subarray(added, 1, 3)));
System.out.println("isEmpty(new int[0]) = " + ArrayUtils.isEmpty(new int[0]));
System.out.println("isEmpty(null) = " + ArrayUtils.isEmpty((int[]) null));
int[] dup = {1, 2, 3, 2};
System.out.println("indexOf([1,2,3,2], 2) = " + ArrayUtils.indexOf(dup, 2));
System.out.println("indexOf([1,2,3,2], 2, 2) = " + ArrayUtils.indexOf(dup, 2, 2));
System.out.println("indexOf([1,2,3], 9) = " + ArrayUtils.indexOf(arr, 9));
System.out.println("contains([1,2,3], 2) = " + ArrayUtils.contains(arr, 2));
System.out.println("add(null, \"x\") = " + Arrays.toString(ArrayUtils.add((String[]) null, "x")));
}
}
5.1 字符串与整数转布尔:toBoolean
运行整类的真实回显(本节先看 BooleanUtils 段):
== BooleanUtils ==
toBoolean("yes") = true
toBoolean("y") = true
toBoolean("on") = true
toBoolean("true") = true
toBoolean("1") = true
toBoolean("no") = false
toBoolean(null) = false
toBoolean(1) = true
toBoolean(0) = false
要点:
- 字符串重载接受 "true"/"on"/"yes"/"y"(忽略大小写),实测 "1" 也返回 true——解析配置文件时容易踩到的非直觉点。
- "no"、null、未知字符串一律返回 false,不抛异常;需要区分「非法值」时不要用这个重载。
- 整数重载按非零判断:
toBoolean(1) = true、toBoolean(0) = false。
5.2 整数映射、判真与取反:toInteger、isTrue、negate
同上类的真实回显:
toInteger(true, 1, 0, -1) = 1
isTrue(Boolean.TRUE) = true
isTrue(null) = false
negate(Boolean.TRUE) = false
negate(null) = null
要点:
toInteger(bool, trueValue, falseValue, nullValue)把三种状态映射为三个整数,避免手写 if-else。isTrue(null)返回 false 而非 NPE;同理还有 isFalse/isNotTrue 系列。negate对 null 返回 null(三值逻辑),对 TRUE/FALSE 正常取反。
六、ArrayUtils 详解
ArrayUtils 补齐了 JDK 数组的增删截查能力。注意:数组长度不可变,add/remove 返回的是新数组。
6.1 增删截:add、remove、subarray
源码见 5.1 的 BooleanArrayDemo.java(ArrayUtils 段),真实回显:
== ArrayUtils ==
add([1,2,3], 4) = [1, 2, 3, 4]
remove([1,2,3,4], 1) = [1, 3, 4]
subarray([1,2,3,4], 1, 3) = [2, 3]
要点:
add追加元素产生新数组;remove(index)按下标删除(下标 1 是第二个元素)。subarray(begin, end)左闭右开,与Arrays.copyOfRange语义一致,但对下标越界更宽容(自动截边界)。
6.2 判空与查找:isEmpty、indexOf、contains
同上类的真实回显:
isEmpty(new int[0]) = true
isEmpty(null) = true
indexOf([1,2,3,2], 2) = 1
indexOf([1,2,3,2], 2, 2) = 3
indexOf([1,2,3], 9) = -1
contains([1,2,3], 2) = true
add(null, "x") = [x]
要点:
isEmpty对空数组与 null 都返回 true。indexOf支持从指定下标开始找(fromIndex=2时找到第二个 2 的位置 3);找不到返回 -1。- 对 null 数组 add 会自动新建数组:
add(null, "x") = [x],省掉一处判空。
七、ObjectUtils 详解
ObjectUtils 处理对象级判空与默认值兜底。源码 /opt/lang-demo/src/main/java/demo/ExceptionSystemDemo.java(完整源码与 ExceptionUtils/SystemUtils 部分见《Apache Commons Lang 3.21.0 进阶 API 与废弃迁移详解》,本节截取 ObjectUtils 段):
package demo;
import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.time.DurationFormatUtils;
public class ExceptionSystemDemo {
public static void main(String[] args) {
System.out.println("== ObjectUtils ==");
System.out.println("defaultIfNull(null, \"dft\") = " + ObjectUtils.defaultIfNull(null, "dft"));
System.out.println("firstNonNull(null, \"x\") = " + ObjectUtils.firstNonNull(null, "x"));
System.out.println("firstNonNull(null, null) = " + ObjectUtils.firstNonNull(null, null));
System.out.println("allNull(null, null) = " + ObjectUtils.allNull(null, null));
System.out.println("allNull(null, \"a\") = " + ObjectUtils.allNull(null, "a"));
System.out.println("anyNull(\"a\", null) = " + ObjectUtils.anyNull("a", null));
System.out.println("anyNull(\"a\", \"b\") = " + ObjectUtils.anyNull("a", "b"));
}
}
说明:实际源码还包含 ExceptionUtils、SystemUtils、MutableInt、DurationFormatUtils 段(进阶篇内容),为聚焦本节仅展示 ObjectUtils 段;运行输出取其对应片段,命令与全文运行完全一致。
运行真实回显(ObjectUtils 段):
== ObjectUtils ==
defaultIfNull(null, "dft") = dft
firstNonNull(null, "x") = x
firstNonNull(null, null) = null
allNull(null, null) = true
allNull(null, "a") = false
anyNull("a", null) = true
anyNull("a", "b") = false
要点:
firstNonNull返回第一个非 null 参数,全 null 时返回 null。allNull/anyNull是多参数判空的直接表达,省掉链式||。
7.1 废弃提示与替代写法(实测)
defaultIfNull(T,T) 在 3.21.0 已 @Deprecated(第三章编译 WARNING 实录),但功能正常。替代方法是 getIfNull(obj, default),实测编译无任何告警(验证类 DepCheck.java,放在 /opt/lang-jars):
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.mutable.MutableInt;
public class DepCheck {
public static void main(String[] args) {
System.out.println("getIfNull(null, \"dft\") = " + ObjectUtils.getIfNull((String) null, "dft"));
System.out.println("getIfNull(null, supplier) = " + ObjectUtils.getIfNull((String) null, () -> "dft-supp"));
MutableInt mi = new MutableInt(3);
System.out.println("mi.intValue() = " + mi.intValue());
System.out.println("mi.incrementAndGet() = " + mi.incrementAndGet());
}
}
编译并运行(-Xlint:deprecation 全量检查,无告警输出):
cd /opt/lang-jars
javac -Xlint:deprecation -encoding UTF-8 -cp /root/.m2/repository/org/apache/commons/commons-lang3/3.21.0/commons-lang3-3.21.0.jar -d . DepCheck.java
java -Dfile.encoding=UTF-8 -cp .:/root/.m2/repository/org/apache/commons/commons-lang3/3.21.0/commons-lang3-3.21.0.jar DepCheck
输出(实测):
getIfNull(null, "dft") = dft
getIfNull(null, supplier) = dft-supp
mi.intValue() = 3
mi.incrementAndGet() = 4
要点:
getIfNull(obj, default)与getIfNull(obj, Supplier)两个重载在 3.21.0 均未废弃,直接作为defaultIfNull的替代;Supplier 版可延迟构造默认值。- 迁移成本为零:
ObjectUtils.defaultIfNull(a, b)逐字替换为ObjectUtils.getIfNull(a, b)。
八、注意事项
- null 安全不是「无约定」:每个方法对 null 的返回值是固定的(isEmpty→true、split→null、left→null 等),写代码前按本文实测口径对齐,避免「以为返回 null 结果是 true」之类的误判。
- 数组方法返回新数组:
ArrayUtils.add/remove/subarray都不改原数组,必须接住返回值(5.1 源码中int[] added = ArrayUtils.add(arr, 4)的写法)。 - 废弃 API 清单:本文涉及的
StringUtils.defaultString(String,String)、ObjectUtils.defaultIfNull已 @Deprecated;连同 Range/MutableInt/Random 系的完整废弃清单与逐项迁移写法,统一见《Apache Commons Lang 3.21.0 进阶 API 与废弃迁移详解》第十一章总表。 - BooleanUtils 字符串重载不抛异常:未知串返回 false,解析强校验场景请自行前置正则或用
toBooleanObject(可区分第三态)。 - 编码:编译期
project.build.sourceEncoding=UTF-8、运行期-Dfile.encoding=UTF-8,两者独立配置(实录见《Ubuntu 22.04 安装 Apache Commons Lang 指南》第七章与 FAQ)。
九、常见问题(FAQ)
Q1:StringUtils 传 null 会抛 NPE 吗?
不会。这是该类与手写 str.isEmpty() 先判空的差异所在,实测口径:isEmpty(null)=true、isBlank(null)=true、split(null, ',')=null、left(null, 3)=null、capitalize(null)=null(4.1~4.5 各段真实回显)。只有 abbreviate 的宽度非法等「参数非法」场景才抛 IllegalArgumentException(4.3 实测)。
Q2:defaultString(null, "N/A") 编译出现 deprecated 告警怎么办?
3.21.0 只废弃了双参重载,单参 defaultString(String) 未废弃。替代写法三选一:改用单参版本;用三元表达式 str == null ? "N/A" : str;用 JDK 自带 Objects.toString(str, "N/A")。功能完全等价(4.5 实测双参返回 N/A)。
Q3:BooleanUtils.toBoolean("1") 为什么返回 true?
字符串重载的真值集合是 "true"/"on"/"yes"/"y"(忽略大小写),3.21.0 中 "1" 也在真值集合里(5.1 实测 toBoolean("1") = true)。反直觉点在于:整数重载 toBoolean(1) 也为 true,但两者语义不同——字符串版是「集合匹配」,整数版是「非零即真」。若希望把 "1" 视为非法输入,需前置校验。
Q4:split 结果和 JDK 的 String.split 不一样?
不一样且差异有两处:一是 Commons 的 split 丢弃全部空 token(a,b,,c 得 3 个),JDK 版保留中间空 token 只丢弃尾部;二是 Commons 对 null 输入返回 null,JDK 版抛 NPE。需要保留空位时用 splitPreserveAllTokens(4.2 实测两者输出对比)。
Q5:ObjectUtils.defaultIfNull 还能用吗?
能,功能正常(第七章实测返回 dft),只是 3.21.0 标记了 @Deprecated。新代码直接用 getIfNull(7.1 实测无告警),存量代码可在升级时批量替换,行为无差异。
十、参考链接
- StringUtils 官方 Javadoc(3.21.0):https://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/StringUtils.html
- BooleanUtils 官方 Javadoc:https://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/BooleanUtils.html
- ArrayUtils 官方 Javadoc:https://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/ArrayUtils.html
- ObjectUtils 官方 Javadoc:https://commons.apache.org/proper/commons-lang/javadocs/api-release/org/apache/commons/lang3/ObjectUtils.html
- 环境搭建与依赖引入:《Ubuntu 22.04 安装 Apache Commons Lang 指南》
- 进阶工具类与废弃迁移:《Apache Commons Lang 3.21.0 进阶 API 与废弃迁移详解》