An Introduction to Apache Commons Lang 3 – Apache Commons Lang 3简介

最后修改: 2018年 9月 15日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

The Apache Commons Lang 3 library is a popular, full-featured package of utility classes, aimed at extending the functionality of the Java API.

Apache Commons Lang 3库 是一个流行的、全功能的实用类包,旨在扩展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).

该库的内容相当丰富,从字符串、数组和数字操作、反射和并发,到几个有序数据结构的实现,如成对和成列(一般称为图ples)。

In this tutorial, we’ll take a deep dive at the library’s most useful utility classes.

在本教程中,我们将深入研究库中最有用的实用类

2. The Maven Dependency

2.Maven的依赖性

As usual, to get started using Apache Commons Lang 3, we first need to add the Maven dependency:

像往常一样,要开始使用Apache Commons Lang 3,我们首先需要添加Maven依赖项

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

3. The StringUtils Class

3.StringUtils

The first utility class that we’ll cover in this introductory roundup is StringUtils.

我们在这个入门综述中要介绍的第一个实用类是StringUtils.

As its name suggests, StringUtils allows us to perform a bunch of null-safe strings operations that complement/extend the ones that java.lang.String provides out of the box.

顾名思义,StringUtils允许我们执行一堆空安全的strings操作,这些操作补充/扩展了java.lang.String提供的开箱即用

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.

当然,StringUtils类实现了许多其他方法,为了简单起见,我们在这里省略了这些。

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

4.ArrayUtils

The ArrayUtils class implements a batch of utility methods that allow us to process and check arrays in many different shapes and forms.

ArrayUtils类实现了一批实用方法,使我们能够处理和检查许多不同形状和形式的数组

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:

让我们从toString()方法的两个重载实现开始,该方法返回给定数组字符串表示,当数组为空时,返回一个特定的字符串

@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 hasCode() and toMap() methods.

接下来,我们有hasCode()toMap()方法。

The former generates a custom hashCode implementation for an array, while the latter converts an array to a Map:

前者为数组生成一个自定义的hashCode实现,而后者将数组转换为Map/em>。

@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.

最后,让我们看看isSameLength() indexOf()方法。

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.

StringUtils类一样,ArrayUtils实现了更多的附加方法。你可以在本教程中了解更多。

In this case, we’ve showcased only the most representative ones.

在这种情况下,我们只展示了最具代表性的那些。

5. The NumberUtils Class

5.NumberUtils

Another key component of Apache Commons Lang 3 is the NumberUtils class.

Apache Commons Lang 3的另一个关键组件是NumberUtils类。

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:

让我们看看compare()方法的重载实现,该方法比较了不同基元的平等性,例如intlong

@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.

此外,存在对compare()进行操作的byteshort的实现,其工作原理与上述例子非常相似。

Next in this review are the createNumber() and isDigit() methods.

接下来是 createNumber()isDigit()方法。

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:

当涉及到寻找一个提供的数组的混合值和最大值时,NumberUtils类通过min()max()方法的重载实现为这些操作提供了强大的支持。

@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

6. 分数

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.

虽然分数的操作肯定不是我们在日常开发工作中最经常要处理的任务,但Fraction类为直接执行这些操作提供了宝贵的支持。

7. The SystemUtils Class

7、SystemUtils

Sometimes, we need to obtain some dynamic information about different properties and variables of the underlying Java platform or the operating system.

有时,我们需要获得一些关于底层Java平台或操作系统的不同属性和变量的动态信息。

Apache Commons Lang 3 provides the SystemUtils class for accomplishing this in a painless way.

Apache Commons Lang 3提供了SystemUtils,以一种无痛的方式完成这一任务

Let’s consider, for example, the getJavaHome(), getUserHome() and isJavaVersionAtLeast() methods:

让我们考虑一下,例如,getJavaHome()getUserHome()isJavaVersionAtLeast()方法。

@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.

SystemUtils类实现了一些额外的实用方法。为了使例子简短,我们省略了这些方法。

8. The Lazy Initialization and Builder Classes

8.懒惰的初始化和生成器类

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.

Apache Commons Lang 3最吸引人的一面是实现了一些著名的设计模式,包括lazy-initializationbuilder模式

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.

例如,假设我们创建了一个昂贵的User类(为简洁起见没有显示),并希望将其实例化推迟到真正需要的时候。

In such a case, all that we need to do is to extend the parameterized LazyInitializer abstract class and override its initialize() method:

在这种情况下,我们需要做的就是扩展参数化的LazyInitializer抽象类并重写其initialize()方法。

public class UserInitializer extends LazyInitializer<User> {

    @Override
    protected User initialize() {
        return new User("John", "john@domain.com");
    }
}

Now, if we want to get our costly User object when it’s required, we just call the UserInitializer’s get() method:

现在,如果我们想在需要时获得我们昂贵的User对象,我们只需调用UserInitializer的get()方法。

@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:

get()方法是实例字段的双重检查成语(线程安全)的实现,这在Joshua Bloch的《Effective Java》第71项中有所规定。

private volatile User instance;
 
User get() { 
    if (instance == null) { 
        synchronized(this) { 
            if (instance == null) 
                instance = new User("John", "john@domain.com"); 
            }
        } 
    } 
    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:

此外,Apache Commons Lang 3实现了HashCodeBuilder类,它允许我们根据典型的流畅API,通过向构建器提供不同的参数来生成hashCode()实现。

@Test
public void whenCalledtoHashCode_thenCorrect() {
    int hashcode = new HashCodeBuilder(17, 37)
      .append("John")
      .append("john@domain.com")
      .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:

我们可以用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. The ConstructorUtils Class

9.ConstructorUtils

Reflection is a first-class citizen in Apache Commons Lang 3.

在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:

例如,假设我们已经实现了一个天真的User域类。

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:

假设它的参数化构造函数是public,我们可以用ConstructorUtils类轻松访问它。

@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:

除了通过构造函数进行标准的类实例化外,我们可以通过调用invokeConstructor()invokeExactConstructor()方法来反射性地创建User实例。

@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

10.FieldUtils

Similarly, we can use the methods of the FieldUtils class for reflectively reading/writing class fields.

同样,我们可以使用FieldUtils类的方法来反思读/写类字段

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.

假设我们想得到User类的一个字段,或者最终得到该类从超类继承的一个字段。

In such a case, we can invoke the getField() method:

在这种情况下,我们可以调用getField()方法。

@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:

另外,如果我们想使用更严格的反射范围,并且只获得在User 类中声明的字段,而不是从超类继承的字段,我们就可以使用getDeclaredField()方法。

@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:

此外,我们可以使用getAllFields()方法来获取所反映的类的字段数量,并使用writeField()writeDeclaredField()方法将一个值写入一个已声明的字段或一个在层次结构中定义的字段。

@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

11.MethodUtils

Along the same lines, we can use reflection on class methods with the MethodUtils class.

按照同样的思路,我们可以用MethodUtils类对类方法进行反射。

In this case, the visibility of the User class’ getName() method is public. So, we can access it with the getAccessibleMethod() method:

在这种情况下,User类的getName()方法的可见性是public。因此,我们可以用getAccessibleMethod()方法访问它。

@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:

当涉及到反射式调用方法时,我们可以使用invokeExactMethod()invokeMethod()方法。

@Test
public 
  void whenCalledinvokeExactMethod_thenCorrect() 
  throws Exception {
    assertThat(MethodUtils.invokeExactMethod(new User("John", "john@domain.com"), "getName"))
     .isEqualTo("John");
}

@Test
public void whenCalledinvokeMethod_thenCorrect() 
  throws Exception {
    User user = new User("John", "john@domain.com");
    Object method = MethodUtils.invokeMethod(user, true, "setName", "John");
    assertThat(user.getName()).isEqualTo("John");
}

12. The MutableObject Class

12.MutableObject

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.

此外,创建可变体类需要大量的模板代码,这些代码可以由大多数IDE通过自动生成的设置器生成。

To this end, Apache Commons Lang 3 provides the MutableObject class, a simple wrapper class for creating mutable objects with minimal fuss:

为此,Apache Commons Lang 3提供了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");    
}

Of course, this is just an example of how to use the MutableObject class.

当然,这只是一个如何使用MutableObject类的例子。

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

13.MutablePair

Interestingly enough, Apache Commons Lang 3 provides strong support for tuples, in the form of pairs and triples.

有趣的是,Apache Commons Lang 3为图元提供了强大的支持,以对和三联的形式。

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:

在这种情况下,我们会使用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");
}

The most relevant detail worth stressing here is the class’ clean API.

这里最值得强调的相关细节是该类的清洁API。

It allows us to set and access the left and right objects wrapped by the pair through the standard setters/getters.

它允许我们通过标准的setters/getters来设置和访问由这对对象包裹的左和右对象。

14. The ImmutablePair Class

14.ImmutablePair

Unsurprisingly, there’s also an immutable counterpart implementation of the MutablePair class, called ImmutablePair:

不出所料,MutablePair类也有一个不可变的对应实现,称为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.

正如我们对不可变类的期望,任何试图通过setValue()方法来改变该对的内部状态的行为都会导致抛出UnsupportedOperationException异常。

15. The Triple Class

15.三重

The last utility class that will look at here is Triple.

这里要看的最后一个实用类是Triple

As the class is abstract, we can create Triple instances by using the of() static factory method:

由于该类是抽象的,我们可以通过使用of()静态工厂方法来创建Triple实例。

@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.

通过MutableTripleImmutableTriple类,也有针对可变和不可变的三元组的具体实现。

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.

在这种情况下,我们将直接跳过它们,因为它们的API看起来与MutablePairImmutablePair类的非常相似。

16. Conclusion

16.结论

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.

在本教程中,我们深入研究了Apache Commons Lang 3提供的一些最有用的实用类off

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.

关于完整的库API,请查看官方的Javadocs

As usual, all the code samples shown in this tutorial are available over on GitHub.

像往常一样,本教程中显示的所有代码样本都可以在GitHub上获得。