1. 概述

尽管Bytebyte基本类型的包装类,且单个值的自动转换可以通过自动装箱(autoboxing)来完成,但值得注意的是,这种自动转换并不适用于数组。本文将深入探讨在Java中将byte数组转换为Byte数组以及反之的操作方法。

2. 依赖

为了演示一种转换方法,我们将使用Apache Commons Lang库。让我们在pom.xml中添加其依赖:

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

3. Byte.valueOf()byteValue()

我们将首先探索使用Byte.valueOf()Byte对象的byteValue()方法在循环中进行转换。

3.1. Byte.valueOf()

Byte.valueOf(byte b)方法返回一个带有输入参数byte值的Byte实例。

让我们使用Byte.valueOf(byte b)将数组中的每个byte转换为包装对象,并通过循环遍历数组:

private static final byte[] PRIMITIVE_BYTE_ARRAY = {65, 66, 67, 68};
private static final Byte[] EXPECTED_ARRAY_VALUES = {65, 66, 67, 68};

@Test
void givenPrimitiveByteArray_whenConvertingUsingByteValueOf_thenGiveExpectedResult() {
    Byte[] newByteArray = new Byte[PRIMITIVE_BYTE_ARRAY.length];
    for (int i = 0; i < PRIMITIVE_BYTE_ARRAY.length; i++) {
        newByteArray[i] = Byte.valueOf(PRIMITIVE_BYTE_ARRAY[i]);
    }
    Assertions.assertThat(newByteArray)
      .containsExactly(EXPECTED_ARRAY_VALUES);
}

如我们所见,所有字节都被复制到新的Byte[]中,且所有值都保留在原位置。

3.2. Byte.byteValue()

Byte对象的byteValue()方法返回其中包含的基本byte值。让我们遍历Byte[]并为每个元素调用此方法:

private static final byte[] EXPECTED_ARRAY_VALUES = {65, 66, 67, 68};
private static final Byte[] BYTE_ARRAY = {65, 66, 67, 68};

@Test
void givenByteArray_whenConvertingUsingByteValue_thenGiveExpectedResult() {
    byte[] newByteArray = new byte[BYTE_ARRAY.length];
    for (int i = 0; i < BYTE_ARRAY.length; i++) {
        newByteArray[i] = BYTE_ARRAY[i].byteValue();
    }
    Assertions.assertThat(newByteArray)
      .containsExactly(EXPECTED_ARRAY_VALUES);
}

正如预期,我们使用反装箱将字节复制到了基本数组中。

4. 自动装箱与反装箱

我们可以使用自动装箱和反装箱更直接地重写上面的代码,以在必要时将byte值转换为Byte实例,反之亦然。

如果我们分解接下来的代码片段,我们可以使用javap工具查看它们的底层实现——自动装箱实际上是调用了Byte.valueOf()方法,而反装箱则是在Byte对象上调用byteValue()方法。因此,从技术上讲,这是相同的逻辑,只是代码更简洁。

4.1. 自动装箱

让我们使用自动装箱将数组中的每个byte转换为包装对象,并通过循环遍历数组:

@Test
void givenPrimitiveIntArray_whenConvertingAutoboxing_thenGiveExpectedResult() {
    Byte[] newByteArray = new Byte[PRIMITIVE_BYTE_ARRAY.length];
    for (int i = 0; i < PRIMITIVE_BYTE_ARRAY.length; i++) {
        newByteArray[i] = PRIMITIVE_BYTE_ARRAY[i];
    }
    Assertions.assertThat(newByteArray)
      .containsExactly(EXPECTED_ARRAY_VALUES);
}

正如我们所见,所有字节都被复制到新的Byte[]中,且所有值都保留在原位置。

4.2. 反装箱

现在,我们将执行相反的操作,将Byte[]转换为其基本类型版本:

@Test
void givenByteArray_whenConvertingUsingUnboxing_thenGiveExpectedResult() {
    byte[] newByteArray = new byte[BYTE_ARRAY.length];
    for (int i = 0; i < BYTE_ARRAY.length; i++) {
        newByteArray[i] = BYTE_ARRAY[i];
    }
    Assertions.assertThat(newByteArray)
      .containsExactly(EXPECTED_ARRAY_VALUES);
}

正如预期,我们使用反装箱将字节复制到了基本数组中。

5. Arrays.setAll()

从Java 8开始,我们可以使用Arrays.setAll(T[] array, IntFunction<? extends T> generator)简化代码,无需循环。 在第一个参数中,我们将发送目标数组,第二个参数是一个函数,用于为每个元素设置新值。

让我们使用Arrays.setAll()将基本byte数组转换为Byte对象数组:

@Test
void givenPrimitiveByteArray_whenConvertingUsingAutoboxingAndArraysSetAll_thenGiveExpectedResult() {
    Byte[] newByteArray = new Byte[PRIMITIVE_BYTE_ARRAY.length];
    Arrays.setAll(newByteArray, n -> PRIMITIVE_BYTE_ARRAY[n]);
    Assertions.assertThat(newByteArray)
      .containsExactly(EXPECTED_ARRAY_VALUES);
}

正如预期,我们使用更少的代码成功地进行了转换。

6. Apache Commons Lang库的ArrayUtils

Apache Commons Lang库中的ArrayUtils是一个提供处理数组各种方法的实用工具类。我们可以使用ArrayUtils.toObject(bytes[] bytes)将基本数组转换为Byte对象数组,反过来,可以使用ArrayUtils.toPrimitive(Byte[] byteObjects)创建基本byte数组。

6.1. ArrayUtils.toObject()

让我们使用ArrayUtils.toObject()将基本bytes数组转换为Byte[]

@Test
void givenPrimitiveByteArray_whenConvertingUsingArrayUtils_thenGiveExpectedResult() {
    Byte[] newByteArray = ArrayUtils.toObject(PRIMITIVE_BYTE_ARRAY);
    Assertions.assertThat(newByteArray)
      .containsExactly(EXPECTED_ARRAY_VALUES);
}

我们仅用一行代码就成功完成了转换。

6.2. ArrayUtils.toPrimitive()

现在,让我们使用ArrayUtils.toPrimitive()执行相反操作:

@Test
void givenByteArray_whenConvertingArrayUtils_thenGiveExpectedResult() {
    byte[] newByteArray = ArrayUtils.toPrimitive(BYTE_ARRAY);
    Assertions.assertThat(newByteArray)
      .containsExactly(EXPECTED_ARRAY_VALUES);
}

我们从Byte[]创建了一个基本bytes数组。

7. 总结

在这篇文章中,我们研究了多种将Byte转换为byte数组以及反之的操作方式。选择哪种方法取决于具体场景。对于已经包含Apache Commons库的项目,使用ArrayUtils可能是更合理的选择,因为它是最简短的实现方式。

如往常一样,完整的源代码可以在GitHub上找到。