Contents

Guava中PreConditions简介

1. 概述

在本教程中,我们将展示如何使用 Google Guava 的Preconditions类。

Preconditions类提供了一个静态方法列表,用于检查是否使用有效参数值调用了方法或构造函数。如果先决条件失败,则会引发定制的异常。

2. Google Guava 的PreConditions

Preconditions类中的每个静态方法都有三个变体:

  • 没有争论。抛出异常而没有错误消息
  • 一个额外的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确保传递给调用方法的参数的真实性。此方法接受布尔条件并在条件为假时抛出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(含)到 size(不含)。你不直接传递一个列表、字符串或数组,你只传递它的大小。如果索引不是有效的元素索引,此方法将引发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,则抛出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(含)到 size(含)。你不直接传递列表、字符串或数组,你只传递它的大小。

如果传递的索引不在 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方法检查对象状态的有效性,并且不依赖于方法参数。例如,一个迭代器可能会使用它来检查是否在任何调用删除之前调用了下一个。如果对象的状态(作为参数传递给方法的布尔值)处于无效状态,则此方法将引发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();
}