1. 概要

このチュートリアルでは、GoogleGuavaの前提条件クラスの使用方法を示します。

Preconditions クラスは、メソッドまたはコンストラクターが有効なパラメーター値で呼び出されていることを確認するための静的メソッドのリストを提供します。 前提条件が失敗した場合、調整された例外がスローされます。

2. GoogleGuavaの前提条件

Preconditions クラスの各静的メソッドには、次の3つのバリアントがあります。

  • 引数はありません。 エラーメッセージなしで例外がスローされます
  • エラーメッセージとして機能する追加のObject引数。 例外はエラーメッセージとともにスローされます
  • 追加のString引数。任意の数の追加のObject引数が、プレースホルダー付きのエラーメッセージとして機能します。 これはprintfと少し似ていますが、GWTの互換性と効率性のために、%sインジケーターのみを許可します。

Preconditionsクラスの使用方法を見てみましょう。

2.1. Mavenの依存関係

pom.xmlにGoogleのGuavaライブラリの依存関係を追加することから始めましょう。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

依存関係の最新バージョンはここで確認できます。

3. checkArgument

PreconditionsクラスメソッドcheckArgumentは、呼び出し元のメソッドに渡されるパラメーターの真実性を保証します。 このメソッドはブール条件を受け入れ、条件がfalseの場合にIllegalArgumentExceptionをスローします。

いくつかの例を使用して、このメソッドをどのように使用できるかを見てみましょう。

3.1. エラーメッセージなし

checkArgument メソッドに追加のパラメーターを渡すことなく、checkArgumentを使用できます。

@Test
public void whenCheckArgumentEvaluatesFalse_throwsException() {
    int age = -18;
 
    assertThatThrownBy(() -> Preconditions.checkArgument(age > 0))
      .isInstanceOf(IllegalArgumentException.class)
      .hasMessage(null).hasNoCause();
}

3.2. エラーメッセージ付き

エラーメッセージを渡すことにより、checkArgumentメソッドから意味のあるエラーメッセージを取得できます。

@Test
public void givenErrorMsg_whenCheckArgEvalsFalse_throwsException() {
    int age = -18;
    String message = "Age can't be zero or less than zero.";
 
    assertThatThrownBy(() -> Preconditions.checkArgument(age > 0, message))
      .isInstanceOf(IllegalArgumentException.class)
      .hasMessage(message).hasNoCause();
}

3.3. テンプレートエラーメッセージ付き

エラーメッセージを渡すことにより、checkArgumentメソッドから動的データとともに意味のあるエラーメッセージを取得できます。

@Test
public void givenTemplateMsg_whenCheckArgEvalsFalse_throwsException() {
    int age = -18;
    String message = "Age should be positive number, you supplied %s.";
 
    assertThatThrownBy(
      () -> Preconditions.checkArgument(age > 0, message, age))
      .isInstanceOf(IllegalArgumentException.class)
      .hasMessage(message, age).hasNoCause();
}

4. checkElementIndex

メソッドcheckElementIndexは、インデックスがリスト、文字列、または指定されたサイズの配列内の有効なインデックスであることを確認します。 要素インデックスは、0を含むものからサイズを含まないものまでの範囲で指定できます。 リスト、文字列、または配列を直接渡すのではなく、そのサイズを渡すだけです。 このメソッドは、インデックスが有効な要素インデックスでない場合は IndexOutOfBoundsException をスローし、そうでない場合はメソッドに渡されているインデックスを返します。

checkElementIndex メソッドが例外をスローしたときにエラーメッセージを渡すことで、意味のあるエラーメッセージを表示することにより、このメソッドをどのように使用できるかを見てみましょう。

@Test
public void givenArrayAndMsg_whenCheckElementEvalsFalse_throwsException() {
    int[] numbers = { 1, 2, 3, 4, 5 };
    String message = "Please check the bound of an array and retry";
 
    assertThatThrownBy(() -> 
      Preconditions.checkElementIndex(6, numbers.length - 1, message))
      .isInstanceOf(IndexOutOfBoundsException.class)
      .hasMessageStartingWith(message).hasNoCause();
}

5. checkNotNull

メソッドcheckNotNullは、パラメーターとして指定された値がnullかどうかをチェックします。 チェックされた値を返します。 このメソッドに渡された値がnullの場合、NullPointerExceptionがスローされます。

次に、エラーメッセージを渡して checkNotNull メソッドから意味のあるエラーメッセージを取得する方法を示して、このメソッドの使用方法を示します。

@Test
public void givenNullString_whenCheckNotNullWithMessage_throwsException () {
    String nullObject = null;
    String message = "Please check the Object supplied, its null!";
 
    assertThatThrownBy(() -> Preconditions.checkNotNull(nullObject, message))
      .isInstanceOf(NullPointerException.class)
      .hasMessage(message).hasNoCause();
}

エラーメッセージにパラメータを渡すことにより、checkNotNullメソッドからの動的データに基づいて意味のあるエラーメッセージを取得することもできます。

@Test
public void whenCheckNotNullWithTemplateMessage_throwsException() {
    String nullObject = null;
    String message = "Please check the Object supplied, its %s!";
 
    assertThatThrownBy(
      () -> Preconditions.checkNotNull(nullObject, message, 
        new Object[] { null }))
      .isInstanceOf(NullPointerException.class)
      .hasMessage(message, nullObject).hasNoCause();
}

6. checkPositionIndex

メソッドcheckPositionIndexは、このメソッドに引数として渡されたインデックスが、指定されたサイズのリスト、文字列、または配列内の有効なインデックスであることを確認します。 位置インデックスは、0からサイズまでの範囲で指定できます。 リスト、文字列、または配列を直接渡すのではなく、そのサイズを渡すだけです。

このメソッドは、渡されたインデックスが0と指定されたサイズの間にない場合、 IndexOutOfBoundsException をスローします。それ以外の場合は、インデックス値を返します。

checkPositionIndexメソッドから意味のあるエラーメッセージを取得する方法を見てみましょう。

@Test
public void givenArrayAndMsg_whenCheckPositionEvalsFalse_throwsException() {
    int[] numbers = { 1, 2, 3, 4, 5 };
    String message = "Please check the bound of an array and retry";
 
    assertThatThrownBy(
      () -> Preconditions.checkPositionIndex(6, numbers.length - 1, message))
      .isInstanceOf(IndexOutOfBoundsException.class)
      .hasMessageStartingWith(message).hasNoCause();
}

7. checkState

メソッドcheckStateは、オブジェクトの状態の有効性をチェックし、メソッドの引数に依存しません。 たとえば、 Iterator はこれを使用して、removeを呼び出す前にnextが呼び出されたことを確認します。 オブジェクトの状態(メソッドに引数として渡されたブール値)が無効な状態の場合、このメソッドはIllegalStateExceptionをスローします。

checkState メソッドが例外をスローしたときにエラーメッセージを渡すことで、意味のあるエラーメッセージを表示することにより、このメソッドをどのように使用できるかを見てみましょう。

@Test
public void givenStatesAndMsg_whenCheckStateEvalsFalse_throwsException() {
    int[] validStates = { -1, 0, 1 };
    int givenState = 10;
    String message = "You have entered an invalid state";
 
    assertThatThrownBy(
      () -> Preconditions.checkState(
        Arrays.binarySearch(validStates, givenState) > 0, message))
      .isInstanceOf(IllegalStateException.class)
      .hasMessageStartingWith(message).hasNoCause();
}

8. 結論

このチュートリアルでは、GuavaライブラリのPreConditionsクラスのメソッドを説明しました。 Preconditions クラスは、メソッドまたはコンストラクターが有効なパラメーター値で呼び出されることを検証するために使用される静的メソッドのコレクションを提供します。

上記の例に属するコードは、 GitHubプロジェクトにあります。これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。