diff --git a/guava-tests/test/com/google/common/collect/ObjectArraysTest.java b/guava-tests/test/com/google/common/collect/ObjectArraysTest.java index a8e7effdaefd..7a5ea92cf2c8 100644 --- a/guava-tests/test/com/google/common/collect/ObjectArraysTest.java +++ b/guava-tests/test/com/google/common/collect/ObjectArraysTest.java @@ -194,6 +194,30 @@ public void testAppendTwoElements() { assertThat(array).asList().containsExactly("foo", "bar", "baz").inOrder(); } + public void testPrependZeroElements_withIncompatibleElementType() { + String[] array = {}; + Object[] result = ObjectArrays.concat(0, array); + assertThat(result).asList().containsExactly(0); + } + + public void testPrependOneElement_withIncompatibleElementType() { + String[] array = {"bar"}; + Object[] result = ObjectArrays.concat(0, array); + assertThat(result).asList().containsExactly(0, "bar").inOrder(); + } + + public void testAppendZeroElements_withIncompatibleElementType() { + String[] array = {}; + Object[] result = ObjectArrays.concat(array, 0); + assertThat(result).asList().containsExactly(0); + } + + public void testAppendOneElement_withIncompatibleElementType() { + String[] array = {"foo"}; + Object[] result = ObjectArrays.concat(array, 0); + assertThat(result).asList().containsExactly("foo", 0).inOrder(); + } + public void testEmptyArrayToEmpty() { doTestNewArrayEquals(new Object[0], 0); } diff --git a/guava/src/com/google/common/collect/ObjectArrays.java b/guava/src/com/google/common/collect/ObjectArrays.java index 3d02072e91d8..aa7da4edb6ab 100644 --- a/guava/src/com/google/common/collect/ObjectArrays.java +++ b/guava/src/com/google/common/collect/ObjectArrays.java @@ -93,10 +93,18 @@ private ObjectArrays() {} * the first position, and the elements of {@code array} occupying the remaining elements. */ public static T[] concat(@ParametricNullness T element, T[] array) { - T[] result = newArray(array, array.length + 1); + Object[] result; + if (element == null || array.getClass().getComponentType().isInstance(element)) { + result = newArray(array, array.length + 1); + } else { + result = new Object[array.length + 1]; + } result[0] = element; arraycopy(array, 0, result, 1, array.length); - return result; + @SuppressWarnings( + "unchecked") // safe: result's component type accepts `element` and all of `array` + T[] typedResult = (T[]) result; + return typedResult; } /** @@ -108,9 +116,18 @@ private ObjectArrays() {} * array}, plus {@code element} occupying the last position. */ public static T[] concat(T[] array, @ParametricNullness T element) { - T[] result = Arrays.copyOf(array, array.length + 1); + Object[] result; + if (element == null || array.getClass().getComponentType().isInstance(element)) { + result = Arrays.copyOf(array, array.length + 1); + } else { + result = new Object[array.length + 1]; + arraycopy(array, 0, result, 0, array.length); + } result[array.length] = element; - return result; + @SuppressWarnings( + "unchecked") // safe: result's component type accepts `element` and all of `array` + T[] typedResult = (T[]) result; + return typedResult; } /**