1. 引言

java.util.Objects 类自 Java 1.7 版本起成为标准库的一部分。这个类提供了处理对象的静态工具方法,用于执行日常任务,例如对象相等性检查、空值检测等。

本文将深入探讨 Java 9 在 java.util.Objects 类中新增的方法,这些工具方法能帮你写出更简洁健壮的代码。

2. requireNonNullElse 方法

这个方法接收两个参数:当第一个参数非 null 时返回它,否则返回第二个参数。如果两个参数都是 null,则抛出 NullPointerException

private List<String> aMethodReturningNullList(){
    return null;
}

@Test
public void givenNullObject_whenRequireNonNullElse_thenElse() {
    List<String> aList = Objects.<List>requireNonNullElse(
      aMethodReturningNullList(), Collections.EMPTY_LIST);
 
    assertThat(aList, is(Collections.EMPTY_LIST));
}

private List<String> aMethodReturningNonNullList() {
    return List.of("item1", "item2");
}

@Test
public void givenObject_whenRequireNonNullElse_thenObject() {
    List<String> aList = Objects.<List>requireNonNullElse(
      aMethodReturningNonNullList(), Collections.EMPTY_LIST);
 
    assertThat(aList, is(List.of("item1", "item2")));
}

@Test(expected = NullPointerException.class)
public void givenNull_whenRequireNonNullElse_thenException() {
    Objects.<List>requireNonNullElse(null, null);
}

核心特点

  • 简单粗暴的空值处理方案
  • 适用于需要默认值的场景
  • 双空值时直接抛出异常

3. requireNonNullElseGet 方法

这个方法与 requireNonNullElse 类似,但第二个参数是 java.util.function.Supplier 接口,支持延迟初始化Supplier 实现负责返回非空对象:

@Test
public void givenObject_whenRequireNonNullElseGet_thenObject() {
    List<String> aList = Objects.<List>requireNonNullElseGet(
      null, List::of);
    assertThat(aList, is(List.of()));
}

⚠️ 使用注意

  • 当默认值创建成本较高时,延迟初始化能提升性能
  • 避免在 Supplier 中抛出异常(除非你故意设计)
  • 适用于需要动态生成默认值的场景

4. checkIndex 方法

用于检查索引是否在有效范围内(0 <= index < length)。返回索引本身,否则抛出 IndexOutOfBoundsException

@Test
public void givenNumber_whenInvokeCheckIndex_thenNumber() {
    int length = 5;
 
    assertThat(Objects.checkIndex(4, length), is(4));
}

@Test(expected = IndexOutOfBoundsException.class)
public void givenOutOfRangeNumber_whenInvokeCheckIndex_thenException() {
    int length = 5;
    Objects.checkIndex(5, length);
}

常见踩坑

  • 边界值检查容易出错(length 本身是非法值)
  • 比手写 if(index < 0 || index >= length) 更简洁
  • 异常信息自动包含边界值,便于调试

5. checkFromToIndex 方法

检查子范围 [fromIndex, toIndex) 是否在 [0, length) 范围内。若子范围有效,返回下界:

@Test
public void givenSubRange_whenCheckFromToIndex_thenNumber() {
    int length = 6;
 
    assertThat(Objects.checkFromToIndex(2,length,length), is(2));
}

@Test(expected = IndexOutOfBoundsException.class)
public void givenInvalidSubRange_whenCheckFromToIndex_thenException() {
    int length = 6;
    Objects.checkFromToIndex(2,7,length);
}

📝 数学表示说明

  • [a, b) 表示包含 a 但不包含 b 的范围
  • 方括号 [] 表示包含值,圆括号 () 表示排除值
  • 这个方法特别适合验证数组/集合的子范围操作

6. checkFromIndexSize 方法

checkFromToIndex 类似,但用 size 替代 toIndex。子范围表示为 [fromIndex, fromIndex + size),需确保在 [0, length) 范围内:

@Test
public void givenSubRange_whenCheckFromIndexSize_thenNumber() {
    int length = 6;
 
    assertThat(Objects.checkFromIndexSize(2,3,length), is(2));
}

@Test(expected = IndexOutOfBoundsException.class)
public void givenInvalidSubRange_whenCheckFromIndexSize_thenException() {
    int length = 6;
    Objects.checkFromIndexSize(2, 6, length);
}

适用场景

  • 处理分页查询(offset + limit 验证)
  • 批量操作时的范围检查
  • checkFromToIndex 更符合某些业务逻辑

7. 总结

Java 9 对 java.util.Objects 的扩展展示了 JDK 持续进化的决心。自 Java 7 引入以来,这个工具类一直在稳步增强,新增的方法覆盖了空值处理和边界检查等高频场景。

这些工具方法虽然简单,但能显著减少样板代码。建议在日常开发中优先使用它们,而不是重复造轮子。

本文代码示例可在 GitHub 仓库 获取完整实现。


原始标题:Java 9 java.util.Objects Additions