Apache Commons Lang 3の紹介

Apache Commons Lang 3の紹介

1. 概要

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

ライブラリのレパートリーは、文字列、配列と数値の操作、反映と同時実行から、ペアやトリプル(一般にtuplesとして知られている)などのいくつかの順序付けられたデータ構造の実装に至るまで、非常に豊富です。

このチュートリアルでは、we’ll take a deep dive at the library’s most useful utility classes

2. Mavenの依存関係

いつものように、Apache Commons Lang 3の使用を開始するには、最初にMaven dependencyを追加する必要があります。


    org.apache.commons
    commons-lang3
    3.8

3. StringUtilsクラス

この紹介のまとめで取り上げる最初のユーティリティクラスはStringUtils.です。

その名前が示すように、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

stringが空白、空、小文字、大文字、英数字などであるかどうかを判断するなど、特定の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クラスは他の多くのメソッドを実装しますが、簡単にするためにここでは省略しました。

特定のstringに何らかのタイプの変換アルゴリズムをチェックまたは適用するその他の追加の方法については、check this tutorialを使用してください。

上で説明したものは本当に簡単なので、単体テストは自明である必要があります。

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

the toString()メソッドの2つのオーバーロードされた実装から始めましょう。これは、arrayがnullの場合に、指定されたarrayと特定のstringstring表現を返します。

@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");
}

次に、hasCode()メソッドとtoMap()メソッドがあります。

前者はarray,のカスタムhashCode実装を生成し、後者はarrayMapに変換します。

@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()メソッドを見てみましょう。

前者は2つの配列の長さが同じかどうかを確認するために使用され、後者は特定の要素のインデックスを取得するために使用されます。

@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);
}

StringUtilsクラスと同様に、ArrayUtilsはさらに多くの追加メソッドを実装します。 それらについて詳しくは、this tutorialをご覧ください。

この場合、最も代表的なものだけを紹介しました。

5. NumberUtilsクラス

Apache Commons Lang 3のもう1つの重要なコンポーネントは、NumberUtilsクラスです。

予想通り、the class provides an extensive number of utility methods, aimed at processing and manipulating numeric types

intlongなどのさまざまなプリミティブの同等性を比較するcompare()メソッドのオーバーロードされた実装を見てみましょう。

@Test
public void whenCalledcompareWithIntegers_thenCorrect() {
    assertThat(NumberUtils.compare(1, 1))
      .isEqualTo(0);
}

@Test
public void whenCalledcompareWithLongs_thenCorrect() {
    assertThat(NumberUtils.compare(1L, 1L))
      .isEqualTo(0);
}

さらに、byteshortで動作するcompare()の実装が存在します。これらは、上記の例と非常によく似ています。

このレビューの次は、createNumber()メソッドとisDigit()メソッドです。

1つ目は、stringの数値表現を作成できるようにし、2つ目は、stringが数字のみで構成されているかどうかを確認します。

@Test
public void whenCalledcreateNumber_thenCorrect() {
    assertThat(NumberUtils.createNumber("123456"))
      .isEqualTo(123456);
}

@Test
public void whenCalledisDigits_thenCorrect() {
    assertThat(NumberUtils.isDigits("123456")).isTrue();
}

提供された配列の混合値と最大値を見つけることになると、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.Fraction Class

画分での作業は、ペンと紙を使用する場合はすべてうまくいきます。 しかし、コードを記述するときにこのプロセスの複雑さを経験する必要がありますか? あんまり。

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");
}

分数を使用した操作は、日常の開発作業で取り組む必要のある最も頻繁なタスクではありませんが、Fractionクラスは、これらの操作を簡単に実行するための貴重なサポートを提供します。

7. SystemUtilsクラス

場合によっては、基盤となるJavaプラットフォームまたはオペレーティングシステムのさまざまなプロパティと変数に関する動的情報を取得する必要があります。

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

たとえば、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();
}

SystemUtilsクラスが実装する追加のユーティリティメソッドがいくつかあります。 例を短くするために、これらは省略しています。

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

たとえば、高価なUserクラス(簡潔にするために表示されていません)を作成し、本当に必要になるまでそのインスタンス化を延期したいとします。

このような場合、必要なのは、パラメーター化されたLazyInitializer抽象クラスを拡張し、そのinitialize()メソッドをオーバーライドすることだけです。

public class UserInitializer extends LazyInitializer {

    @Override
    protected User initialize() {
        return new User("John", "[email protected]");
    }
}

ここで、必要なときにコストのかかるUserオブジェクトを取得する場合は、UserInitializer’s 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 inJoshua 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;
}

さらに、Apache Commons Lang 3はHashCodeBuilderクラスを実装します。これにより、一般的な流暢なAPIに基づいて、ビルダーにさまざまなパラメーターを提供することで、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クラス

Reflectionは、Apache Commons Lang3の第一級市民です。

ライブラリにはいくつかのリフレクションクラスが含まれているため、クラスフィールドとメソッドにリフレクションでアクセスして操作できます。

たとえば、単純なUserドメインクラスを実装したとします。

public class User {

    private String name;
    private String email;

    // standard constructors / getters / setters / toString
}

パラメータ化されたコンストラクタがpublicであると仮定すると、ConstructorUtilsクラスを使用して簡単にアクセスできます。

@Test
public void whenCalledgetAccessibleConstructor_thenCorrect() {
    assertThat(ConstructorUtils
      .getAccessibleConstructor(User.class, String.class, String.class))
      .isInstanceOf(Constructor.class);
}

コンストラクタを介した標準のクラスインスタンス化の代わりに、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. FieldUtilsクラス

同様に、we can use the methods of the FieldUtils class for reflectively reading/writing class fields

Userクラスのフィールド、または最終的にはクラスがスーパークラスから継承しているフィールドを取得するとします。

このような場合、getField()メソッドを呼び出すことができます。

@Test
public void whenCalledgetField_thenCorrect() {
    assertThat(FieldUtils.getField(User.class, "name", true).getName())
      .isEqualTo("name");
}

または、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の場合は、getDeclaredField()メソッドを使用します。

@Test
public void whenCalledgetDeclaredFieldForceAccess_thenCorrect() {
    assertThat(FieldUtils.getDeclaredField(User.class, "name", true).getName())
      .isEqualTo("name");
}

さらに、getAllFields()メソッドを使用して、反映されたクラスのフィールド数を取得し、宣言されたフィールドまたはwriteField()と%()を使用して階層で定義されたフィールドに値を書き込むことができます。 t2)sメソッド:

@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クラスのクラスメソッドでリフレクションを使用できます。

この場合、UserクラスのgetName()メソッドの可視性はpublicです。 したがって、getAccessibleMethod()メソッドを使用してアクセスできます。

@Test
public void whenCalledgetAccessibleMethod_thenCorrect() {
    assertThat(MethodUtils.getAccessibleMethod(User.class, "getName"))
      .isInstanceOf(Method.class);
}

メソッドを反射的に呼び出す場合は、invokeExactMethod()メソッドとinvokeMethod()メソッドを使用できます。

@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クラス

While immutability is a key feature of good object-oriented software that we should default to in every possible case、残念ながら、可変オブジェクトを処理する必要がある場合があります。

さらに、可変クラスを作成するには、多くのボイラープレートコードが必要です。これは、自動生成セッターを介してほとんどのIDEで生成できます。

この目的のために、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");
}

もちろん、これはMutableObjectクラスの使用方法の一例にすぎません。

経験則として、we should always strive to create immutable classes, or in the worst case, provide only the required level of mutability

13. MutablePairクラス

興味深いことに、Apache Commons Lang 3はペアとトリプルの形式でタプルを強力にサポートします。

したがって、順序付けられた要素の可変ペアを作成する必要があるとしましょう。

このような場合、MutablePairクラスを使用します。

private static MutablePair 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");
}

ここで強調する価値のある最も関連性のある詳細は、クラスのクリーンなAPIです。

標準のセッター/ゲッターを介して、ペアでラップされた左右のオブジェクトを設定およびアクセスできます。

14. ImmutablePairクラス

当然のことながら、ImmutablePairと呼ばれるMutablePairクラスの不変の対応する実装もあります。

private static ImmutablePair 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");
}

不変のクラスから予想されるように、setValue()メソッドを使用してペアの内部状態を変更しようとすると、UnsupportedOperationException例外がスローされます。

15. The Triple Class

ここで確認する最後のユーティリティクラスはTripleです。

クラスは抽象であるため、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");
}

MutableTripleクラスとImmutableTripleクラスを介して、可変トリプルと不変トリプルの両方の具体的な実装もあります。

静的なファクトリメソッドではなく、パラメータ化されたコンストラクタを介してインスタンスを作成できます。

この場合、APIはMutablePairクラスとImmutablePairクラスのAPIに非常に似ているため、スキップします。

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シェルフ*。

ライブラリは、.を見る価値のある他の多くのユーティリティクラスを実装しています。ここでは、かなり意見の分かれる基準に基づいて、最も有用なものを紹介しました。

完全なライブラリAPIについては、official Javadocsを確認してください。

いつものように、このチュートリアルに示されているすべてのコードサンプルはGitHubで利用できます。