1. 概述
Apache Commons Lang 3 库 是一个功能强大、全面的工具类库,旨在扩展 Java 标准库的功能。
这个库涵盖了从字符串、数组、数值处理,到反射、并发支持,甚至包括一些有序数据结构(如 Pair 和 Triple,统称为 元组)的实现。
在本篇文章中,我们将深入介绍该库中最实用的一些工具类。
2. Maven 依赖
要使用 Apache Commons Lang 3,首先需要添加 Maven 依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
3. StringUtils
类
我们首先介绍的是 StringUtils
类。
顾名思义,**StringUtils
提供了一组空指针安全的字符串操作方法,是对 java.lang.String
类的补充和扩展**。
下面是一些用于判断字符串状态的方法示例,比如是否为空、是否全小写、是否为字母数字等:
@Test
public void whenCalledisBlank_thenCorrect() {
assertThat(StringUtils.isBlank(" ")).isTrue();
}
@Test
public void whenCalledisEmpty_thenCorrect() {
assertThat(StringUtils.isEmpty("")).isTrue();
}
@Test
public void whenCalledisAllLowerCase_thenCorrect() {
assertThat(StringUtils.isAllLowerCase("abd")).isTrue();
}
@Test
public void whenCalledisAllUpperCase_thenCorrect() {
assertThat(StringUtils.isAllUpperCase("ABC")).isTrue();
}
@Test
public void whenCalledisMixedCase_thenCorrect() {
assertThat(StringUtils.isMixedCase("abC")).isTrue();
}
@Test
public void whenCalledisAlpha_thenCorrect() {
assertThat(StringUtils.isAlpha("abc")).isTrue();
}
@Test
public void whenCalledisAlphanumeric_thenCorrect() {
assertThat(StringUtils.isAlphanumeric("abc123")).isTrue();
}
当然,StringUtils
还有很多其他方法,这里为了简洁只列出了一部分。
更多字符串处理方法可以参考 这篇教程。
4. ArrayUtils
类
ArrayUtils
类提供了一组用于数组处理和校验的工具方法。
我们从 toString()
方法开始,它可以把数组转换为字符串表示形式,并支持传入默认值处理 null 数组:
@Test
public void whenCalledtoString_thenCorrect() {
String[] array = {"a", "b", "c"};
assertThat(ArrayUtils.toString(array))
.isEqualTo("{a,b,c}");
}
@Test
public void whenCalledtoStringIfArrayisNull_thenCorrect() {
assertThat(ArrayUtils.toString(null, "Array is null"))
.isEqualTo("Array is null");
}
接着是 hashCode()
和 toMap()
方法:
hashCode()
为数组生成自定义的哈希值;toMap()
将二维数组转换为Map
。
@Test
public void whenCalledhashCode_thenCorrect() {
String[] array = {"a", "b", "c"};
assertThat(ArrayUtils.hashCode(array))
.isEqualTo(997619);
}
@Test
public void whenCalledtoMap_thenCorrect() {
String[][] array = {{"1", "one"}, {"2", "two"}, {"3", "three"}};
Map map = new HashMap();
map.put("1", "one");
map.put("2", "two");
map.put("3", "three");
assertThat(ArrayUtils.toMap(array))
.isEqualTo(map);
}
最后是 isSameLength()
和 indexOf()
方法:
@Test
public void whenCalledisSameLength_thenCorrect() {
int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3};
assertThat(ArrayUtils.isSameLength(array1, array2))
.isTrue();
}
@Test
public void whenCalledIndexOf_thenCorrect() {
int[] array = {1, 2, 3};
assertThat(ArrayUtils.indexOf(array, 1, 0))
.isEqualTo(0);
}
更多数组操作方法可以参考 这篇教程。
5. NumberUtils
类
NumberUtils 类是处理数值类型的核心工具类。
提供了大量用于数值处理的方法,比如比较、转换、最大最小值查找等。
@Test
public void whenCalledcompareWithIntegers_thenCorrect() {
assertThat(NumberUtils.compare(1, 1))
.isEqualTo(0);
}
@Test
public void whenCalledcompareWithLongs_thenCorrect() {
assertThat(NumberUtils.compare(1L, 1L))
.isEqualTo(0);
}
还有用于创建数字对象和判断是否为纯数字的方法:
@Test
public void whenCalledcreateNumber_thenCorrect() {
assertThat(NumberUtils.createNumber("123456"))
.isEqualTo(123456);
}
@Test
public void whenCalledisDigits_thenCorrect() {
assertThat(NumberUtils.isDigits("123456")).isTrue();
}
查找数组中的最大最小值:
@Test
public void whenCalledmaxwithIntegerArray_thenCorrect() {
int[] array = {1, 2, 3, 4, 5, 6};
assertThat(NumberUtils.max(array))
.isEqualTo(6);
}
@Test
public void whenCalledminwithIntegerArray_thenCorrect() {
int[] array = {1, 2, 3, 4, 5, 6};
assertThat(NumberUtils.min(array)).isEqualTo(1);
}
@Test
public void whenCalledminwithByteArray_thenCorrect() {
byte[] array = {1, 2, 3, 4, 5, 6};
assertThat(NumberUtils.min(array))
.isEqualTo((byte) 1);
}
6. Fraction
类
手动处理分数确实有点麻烦,但有了 Fraction
类,一切变得简单粗暴。
@Test
public void whenCalledgetFraction_thenCorrect() {
assertThat(Fraction.getFraction(5, 6)).isInstanceOf(Fraction.class);
}
@Test
public void givenTwoFractionInstances_whenCalledadd_thenCorrect() {
Fraction fraction1 = Fraction.getFraction(1, 4);
Fraction fraction2 = Fraction.getFraction(3, 4);
assertThat(fraction1.add(fraction2).toString()).isEqualTo("1/1");
}
@Test
public void givenTwoFractionInstances_whenCalledsubstract_thenCorrect() {
Fraction fraction1 = Fraction.getFraction(3, 4);
Fraction fraction2 = Fraction.getFraction(1, 4);
assertThat(fraction1.subtract(fraction2).toString()).isEqualTo("1/2");
}
@Test
public void givenTwoFractionInstances_whenCalledmultiply_thenCorrect() {
Fraction fraction1 = Fraction.getFraction(3, 4);
Fraction fraction2 = Fraction.getFraction(1, 4);
assertThat(fraction1.multiplyBy(fraction2).toString()).isEqualTo("3/16");
}
虽然分数处理在日常开发中不常见,但 Fraction
类提供了非常优雅的 API。
7. SystemUtils
类
有时候我们需要获取系统或 Java 环境的一些信息,SystemUtils
类可以帮助你轻松搞定。
@Test
public void whenCalledgetJavaHome_thenCorrect() {
assertThat(SystemUtils.getJavaHome())
.isEqualTo(new File("path/to/java/jdk"));
}
@Test
public void whenCalledgetUserHome_thenCorrect() {
assertThat(SystemUtils.getUserHome())
.isEqualTo(new File("path/to/user/home"));
}
@Test
public void whenCalledisJavaVersionAtLeast_thenCorrect() {
assertThat(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_RECENT)).isTrue();
}
8. 懒加载和构建者模式类
Apache Commons Lang 3 实现了一些常见的设计模式,比如懒加载和构建者模式。
比如懒加载一个昂贵的对象:
public class UserInitializer extends LazyInitializer<User> {
@Override
protected User initialize() {
return new User("John", "[email protected]");
}
}
获取对象时:
@Test
public void whenCalledget_thenCorrect()
throws ConcurrentException {
UserInitializer userInitializer = new UserInitializer();
assertThat(userInitializer.get()).isInstanceOf(User.class);
}
还有 HashCodeBuilder
类,可以帮你快速生成 hashCode()
:
@Test
public void whenCalledtoHashCode_thenCorrect() {
int hashcode = new HashCodeBuilder(17, 37)
.append("John")
.append("[email protected]")
.toHashCode();
assertThat(hashcode).isEqualTo(1269178828);
}
或者用 BasicThreadFactory
构建线程工厂:
@Test
public void whenCalledBuilder_thenCorrect() {
BasicThreadFactory factory = new BasicThreadFactory.Builder()
.namingPattern("workerthread-%d")
.daemon(true)
.priority(Thread.MAX_PRIORITY)
.build();
assertThat(factory).isInstanceOf(BasicThreadFactory.class);
}
9. ConstructorUtils
类
反射是 Commons Lang 3 的一大亮点,ConstructorUtils
可以帮你轻松调用构造器。
@Test
public void whenCalledgetAccessibleConstructor_thenCorrect() {
assertThat(ConstructorUtils
.getAccessibleConstructor(User.class, String.class, String.class))
.isInstanceOf(Constructor.class);
}
或者直接调用构造器创建实例:
@Test
public void whenCalledinvokeConstructor_thenCorrect()
throws Exception {
assertThat(ConstructorUtils.invokeConstructor(User.class, "name", "email"))
.isInstanceOf(User.class);
}
@Test
public void whenCalledinvokeExactConstructor_thenCorrect()
throws Exception {
String[] args = {"name", "email"};
Class[] parameterTypes= {String.class, String.class};
assertThat(ConstructorUtils.invokeExactConstructor(User.class, args, parameterTypes))
.isInstanceOf(User.class);
}
10. FieldUtils
类
FieldUtils
提供了字段的反射操作能力。
@Test
public void whenCalledgetField_thenCorrect() {
assertThat(FieldUtils.getField(User.class, "name", true).getName())
.isEqualTo("name");
}
获取声明字段:
@Test
public void whenCalledgetDeclaredFieldForceAccess_thenCorrect() {
assertThat(FieldUtils.getDeclaredField(User.class, "name", true).getName())
.isEqualTo("name");
}
读写字段:
@Test
public void whenCalledgetAllFields_thenCorrect() {
assertThat(FieldUtils.getAllFields(User.class).length)
.isEqualTo(2);
}
@Test
public void whenCalledwriteField_thenCorrect()
throws IllegalAccessException {
FieldUtils.writeField(user, "name", "Julie", true);
assertThat(FieldUtils.readField(user, "name", true))
.isEqualTo("Julie");
}
@Test
public void givenFieldUtilsClass_whenCalledwriteDeclaredField_thenCorrect() throws IllegalAccessException {
FieldUtils.writeDeclaredField(user, "name", "Julie", true);
assertThat(FieldUtils.readField(user, "name", true))
.isEqualTo("Julie");
}
11. MethodUtils
类
同样地,MethodUtils
提供了方法级别的反射支持。
@Test
public void whenCalledgetAccessibleMethod_thenCorrect() {
assertThat(MethodUtils.getAccessibleMethod(User.class, "getName"))
.isInstanceOf(Method.class);
}
调用方法:
@Test
public
void whenCalledinvokeExactMethod_thenCorrect()
throws Exception {
assertThat(MethodUtils.invokeExactMethod(new User("John", "[email protected]"), "getName"))
.isEqualTo("John");
}
@Test
public void whenCalledinvokeMethod_thenCorrect()
throws Exception {
User user = new User("John", "[email protected]");
Object method = MethodUtils.invokeMethod(user, true, "setName", "John");
assertThat(user.getName()).isEqualTo("John");
}
12. MutableObject
类
虽然不可变对象是首选,但有时我们确实需要可变对象。
@BeforeClass
public static void setUpMutableObject() {
mutableObject = new MutableObject("Initial value");
}
@Test
public void whenCalledgetValue_thenCorrect() {
assertThat(mutableObject.getValue()).isInstanceOf(String.class);
}
@Test
public void whenCalledsetValue_thenCorrect() {
mutableObject.setValue("Another value");
assertThat(mutableObject.getValue()).isEqualTo("Another value");
}
@Test
public void whenCalledtoString_thenCorrect() {
assertThat(mutableObject.toString()).isEqualTo("Another value");
}
13. MutablePair
类
处理有序的两个值,可以使用 MutablePair
:
private static MutablePair<String, String> mutablePair;
@BeforeClass
public static void setUpMutablePairInstance() {
mutablePair = new MutablePair<>("leftElement", "rightElement");
}
@Test
public void whenCalledgetLeft_thenCorrect() {
assertThat(mutablePair.getLeft()).isEqualTo("leftElement");
}
@Test
public void whenCalledgetRight_thenCorrect() {
assertThat(mutablePair.getRight()).isEqualTo("rightElement");
}
@Test
public void whenCalledsetLeft_thenCorrect() {
mutablePair.setLeft("newLeftElement");
assertThat(mutablePair.getLeft()).isEqualTo("newLeftElement");
}
14. ImmutablePair
类
不可变版本的 Pair:
private static ImmutablePair<String, String> immutablePair = new ImmutablePair<>("leftElement", "rightElement");
@Test
public void whenCalledgetLeft_thenCorrect() {
assertThat(immutablePair.getLeft()).isEqualTo("leftElement");
}
@Test
public void whenCalledgetRight_thenCorrect() {
assertThat(immutablePair.getRight()).isEqualTo("rightElement");
}
@Test
public void whenCalledof_thenCorrect() {
assertThat(ImmutablePair.of("leftElement", "rightElement"))
.isInstanceOf(ImmutablePair.class);
}
@Test(expected = UnsupportedOperationException.class)
public void whenCalledSetValue_thenThrowUnsupportedOperationException() {
immutablePair.setValue("newValue");
}
15. Triple
类
三元组支持,通过 Triple.of()
创建:
@BeforeClass
public static void setUpTripleInstance() {
triple = Triple.of("leftElement", "middleElement", "rightElement");
}
@Test
public void whenCalledgetLeft_thenCorrect() {
assertThat(triple.getLeft()).isEqualTo("leftElement");
}
@Test
public void whenCalledgetMiddle_thenCorrect() {
assertThat(triple.getMiddle()).isEqualTo("middleElement");
}
@Test
public void whenCalledgetRight_thenCorrect() {
assertThat(triple.getRight()).isEqualTo("rightElement");
}
16. 总结
在这篇文章中,我们深入介绍了 Apache Commons Lang 3 中一些最实用的工具类。
虽然这只是冰山一角,但足以让你在日常开发中事半功倍。
更多内容可以查阅 官方 Javadoc。
所有代码示例都可以在 GitHub 找到。