1. Overview
The Apache Commons Lang 3 library is a popular, full-featured package of utility classes, aimed at extending the functionality of the Java API.
The library’s repertoire is pretty rich, ranging from string, array and number manipulation, reflection and concurrency, to the implementations of several ordered data structures, like pairs and triples (generically known as tuples).
In this tutorial, we’ll take a deep dive at the library’s most useful utility classes.
2. The Maven Dependency
As usual, to get started using Apache Commons Lang 3, we first need to add the Maven dependency:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
3. The StringUtils Class
The first utility class that we’ll cover in this introductory roundup is StringUtils.
As its name suggests, *StringUtils allows us to perform a bunch of null-safe s*trings operations that complement/extend the ones that java.lang.String provides out of the box**.
Let’s start showcasing the set of utility methods that perform several checks on a given string, such as determining if the string is blank, empty, lowercased, uppercased, alphanumeric and so forth:
@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();
}
Of course, the StringUtils class implements many other methods, which we’ve omitted here for simplicity’s sake.
For some other additional methods that check or apply some type of conversion algorithm to a given string, please check this tutorial.
The ones that we’ve covered above are really straightforward, so the unit tests should be self-explanatory.
4. The ArrayUtils Class
The ArrayUtils class implements a batch of utility methods that allow us to process and check arrays in many different shapes and forms.
Let’s start with the two overloaded implementations of the toString() method, which returns a string representation of the given array and a specific string when the array is 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");
}
Next, we have the hashCode() and toMap() methods.
The former generates a custom hashCode implementation for an array, while the latter converts an array to a 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);
}
Lastly, let’s look at the isSameLength() and indexOf() methods.
The former is used for checking if two arrays have the same length, and the latter for getting the index of a given element:
@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);
}
As with the StringUtils class, ArrayUtils implement a lot more of additional methods. You can learn more about them in this tutorial.
In this case, we’ve showcased only the most representative ones.
5. The NumberUtils Class
Another key component of Apache Commons Lang 3 is the NumberUtils class.
As expected, the class provides an extensive number of utility methods, aimed at processing and manipulating numeric types.
Let’s look at the overloaded implementations of the compare() method, which compares the equality of different primitives, such as int and long:
@Test
public void whenCalledcompareWithIntegers_thenCorrect() {
assertThat(NumberUtils.compare(1, 1))
.isEqualTo(0);
}
@Test
public void whenCalledcompareWithLongs_thenCorrect() {
assertThat(NumberUtils.compare(1L, 1L))
.isEqualTo(0);
}
In addition, there exist implementations of compare() that operate on byte and short, which work very similar to the above examples.
Next in this review are the createNumber() and isDigit() methods.
The first one allows us to create a numeric representation of a string, while the second checks if a string is only composed of digits:
@Test
public void whenCalledcreateNumber_thenCorrect() {
assertThat(NumberUtils.createNumber("123456"))
.isEqualTo(123456);
}
@Test
public void whenCalledisDigits_thenCorrect() {
assertThat(NumberUtils.isDigits("123456")).isTrue();
}
When it comes to finding the mix and max values of a supplied array, the NumberUtils class provides strong support for these operations through the overloaded implementations of the min() and max() methods:
@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. The Fraction Class
Working with fractions is all fine and well when we use a pen and a piece of paper. But, do we have to go through the complexities of this process when writing code? Not really.
The Fraction class makes adding, subtracting and multiplying fractions in a breeze:
@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");
}
While operations with fractions aren’t certainly the most frequent task that we’ll have to tackle in our daily development work, the Fraction class provides valuable support for performing these operations in a straightforward fashion.
7. The SystemUtils Class
Sometimes, we need to obtain some dynamic information about different properties and variables of the underlying Java platform or the operating system.
Apache Commons Lang 3 provides the SystemUtils class for accomplishing this in a painless way.
Let’s consider, for example, the getJavaHome(), getUserHome() and isJavaVersionAtLeast() methods:
@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();
}
There are a few additional utility methods that the SystemUtils class implements. We’ve omitted them to keep the examples short.
8. The Lazy Initialization and Builder Classes
One of Apache Commons Lang 3’s most appealing facet is the implementation of some well-known design patterns, including the lazy-initialization and builder patterns.
For instance, let’s say that we have created an expensive User class (not shown for brevity), and want to defer its instantiation until it’s really needed.
In such a case, all that we need to do is to extend the parameterized LazyInitializer abstract class and override its initialize() method:
public class UserInitializer extends LazyInitializer<User> {
@Override
protected User initialize() {
return new User("John", "[email protected]");
}
}
Now, if we want to get our costly User object when it’s required, we just call the UserInitializer’s get() method:
@Test
public void whenCalledget_thenCorrect()
throws ConcurrentException {
UserInitializer userInitializer = new UserInitializer();
assertThat(userInitializer.get()).isInstanceOf(User.class);
}
The get() method is an implementation of the double-check idiom (thread-safe) for an instance field, as specified in Joshua Bloch’s “Effective Java”, item 71:
private volatile User instance;
User get() {
if (instance == null) {
synchronized(this) {
if (instance == null)
instance = new User("John", "[email protected]");
}
}
}
return instance;
}
In addition, Apache Commons Lang 3 implements the HashCodeBuilder class, which allows us to generate hashCode() implementations by supplying the builder with different parameters, based on a typical fluent API:
@Test
public void whenCalledtoHashCode_thenCorrect() {
int hashcode = new HashCodeBuilder(17, 37)
.append("John")
.append("[email protected]")
.toHashCode();
assertThat(hashcode).isEqualTo(1269178828);
}
We can do something similar with the BasicThreadFactory class, and create daemon threads with a naming pattern and a priority:
@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. The ConstructorUtils Class
Reflection is a first-class citizen in Apache Commons Lang 3.
The library includes several reflection classes, which allows us to reflectively access and manipulate class fields and methods.
For example, let’s say that we’ve implemented a naive User domain class:
public class User {
private String name;
private String email;
// standard constructors / getters / setters / toString
}
Assuming that its parameterized constructor is public, we can easily access it with the ConstructorUtils class:
@Test
public void whenCalledgetAccessibleConstructor_thenCorrect() {
assertThat(ConstructorUtils
.getAccessibleConstructor(User.class, String.class, String.class))
.isInstanceOf(Constructor.class);
}
Alternatively to standard class instantiation via constructors, we can reflectively create User instances by just calling the invokeConstructor() and invokeExactConstructor() methods:
@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. The FieldUtils Class
Similarly, we can use the methods of the FieldUtils class for reflectively reading/writing class fields.
Let’s suppose that we want to get a field of the User class, or eventually a field that the class is inheriting from a superclass.
In such a case, we can invoke the getField() method:
@Test
public void whenCalledgetField_thenCorrect() {
assertThat(FieldUtils.getField(User.class, "name", true).getName())
.isEqualTo("name");
}
Alternatively, if we’d want to use a more restrictive reflection scope, and only get a field declared in the User class, and not inherited from a superclass, we’d just use the getDeclaredField() method:
@Test
public void whenCalledgetDeclaredFieldForceAccess_thenCorrect() {
assertThat(FieldUtils.getDeclaredField(User.class, "name", true).getName())
.isEqualTo("name");
}
In addition, we can use the getAllFields() method for getting the number of fields of the reflected class, and write a value to a declared field or a field defined up in a hierarchy with the writeField() and writeDeclaredField() methods:
@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. The MethodUtils Class
Along the same lines, we can use reflection on class methods with the MethodUtils class.
In this case, the visibility of the User class’ getName() method is public. So, we can access it with the getAccessibleMethod() method:
@Test
public void whenCalledgetAccessibleMethod_thenCorrect() {
assertThat(MethodUtils.getAccessibleMethod(User.class, "getName"))
.isInstanceOf(Method.class);
}
When it comes to reflectively invoking methods, we can use the invokeExactMethod() and invokeMethod() methods:
@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. The MutableObject Class
While immutability is a key feature of good object-oriented software that we should default to in every possible case, unfortunately sometimes we need to deal with mutable objects.
Moreover, creating mutable classes requires a lot of boilerplate code, which can be generated by most IDEs through auto-generated setters.
To this end, Apache Commons Lang 3 provides the MutableObject class, a simple wrapper class for creating mutable objects with minimal fuss:
@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");
}
Of course, this is just an example of how to use the MutableObject class.
As rule of thumb, we should always strive to create immutable classes, or in the worst case, provide only the required level of mutability.
13. The MutablePair Class
Interestingly enough, Apache Commons Lang 3 provides strong support for tuples, in the form of pairs and triples.
So, let’s suppose that we need to create a mutable pair of ordered elements.
In such a case, we’d use the MutablePair class:
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");
}
The most relevant detail worth stressing here is the class’ clean API.
It allows us to set and access the left and right objects wrapped by the pair through the standard setters/getters.
14. The ImmutablePair Class
Unsurprisingly, there’s also an immutable counterpart implementation of the MutablePair class, called ImmutablePair:
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");
}
As we might expect from an immutable class, any attempt to change the pair’s internal state through the setValue() method will result in throwing an UnsupportedOperationException exception.
15. The Triple Class
The last utility class that will look at here is Triple.
As the class is abstract, we can create Triple instances by using the of() static factory method:
@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");
}
There are also concrete implementations for both mutable and immutable triples, through the MutableTriple and ImmutableTriple classes.
We can create their instances via parameterized constructors, rather than with a static factory method.
In this case, we’ll just skip them, as their APIs look very similar to the ones of the MutablePair and ImmutablePair classes.
16. Conclusion
In this tutorial, we took an in-depth look at some of the most useful utility classes that Apache Commons Lang 3 provides off the shelf.
The library implements many other utility classes worth looking at**.** Here, we’ve just showcased the most useful ones, based on a pretty opinionated criterion.
For the full library API, please check the official Javadocs.
As usual, all the code samples shown in this tutorial are available over on GitHub.