From 0a86a7e3a8701b425db4628c965fb1f97feedb6b Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 4 Dec 2025 15:06:08 +0100 Subject: [PATCH] Use == instead of instanceof for primitive array type checks Closes gh-35962 --- ...izedMergedAnnotationInvocationHandler.java | 84 ++++++++++--------- .../org/springframework/util/ObjectUtils.java | 40 ++++----- .../util/ObjectUtilsTests.java | 7 ++ 3 files changed, 71 insertions(+), 60 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java index 8c8f5fc358b..69f34eb28b7 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java @@ -167,31 +167,8 @@ final class SynthesizedMergedAnnotationInvocationHandler i * @return the formatted string representation */ private String toString(Object value) { - if (value instanceof String str) { - return '"' + str + '"'; - } - if (value instanceof Character) { - return '\'' + value.toString() + '\''; - } - if (value instanceof Byte) { - return String.format("(byte) 0x%02X", value); - } - if (value instanceof Long longValue) { - return Long.toString(longValue) + 'L'; - } - if (value instanceof Float floatValue) { - return Float.toString(floatValue) + 'f'; - } - if (value instanceof Double doubleValue) { - return Double.toString(doubleValue) + 'd'; - } - if (value instanceof Enum e) { - return e.name(); - } - if (value instanceof Class clazz) { - return getName(clazz) + ".class"; - } - if (value.getClass().isArray()) { + Class type = value.getClass(); + if (type.isArray()) { StringBuilder builder = new StringBuilder("{"); for (int i = 0; i < Array.getLength(value); i++) { if (i > 0) { @@ -202,6 +179,30 @@ final class SynthesizedMergedAnnotationInvocationHandler i builder.append('}'); return builder.toString(); } + if (type == String.class) { + return '"' + ((String) value) + '"'; + } + if (type == Character.class) { + return '\'' + value.toString() + '\''; + } + if (type == Byte.class) { + return String.format("(byte) 0x%02X", value); + } + if (type == Long.class) { + return Long.toString((Long) value) + 'L'; + } + if (type == Float.class) { + return Float.toString((Float) value) + 'f'; + } + if (type == Double.class) { + return Double.toString((Double) value) + 'd'; + } + if (value instanceof Enum e) { + return e.name(); + } + if (type == Class.class) { + return getName((Class) value) + ".class"; + } return String.valueOf(value); } @@ -226,29 +227,30 @@ final class SynthesizedMergedAnnotationInvocationHandler i * @param array the array to clone */ private Object cloneArray(Object array) { - if (array instanceof boolean[] booleans) { - return booleans.clone(); + Class type = array.getClass(); + if (type == boolean[].class) { + return ((boolean[]) array).clone(); } - if (array instanceof byte[] bytes) { - return bytes.clone(); + if (type == byte[].class) { + return ((byte[]) array).clone(); } - if (array instanceof char[] chars) { - return chars.clone(); + if (type == char[].class) { + return ((char[]) array).clone(); } - if (array instanceof double[] doubles) { - return doubles.clone(); + if (type == double[].class) { + return ((double[]) array).clone(); } - if (array instanceof float[] floats) { - return floats.clone(); + if (type == float[].class) { + return ((float[]) array).clone(); } - if (array instanceof int[] ints) { - return ints.clone(); + if (type == int[].class) { + return ((int[]) array).clone(); } - if (array instanceof long[] longs) { - return longs.clone(); + if (type == long[].class) { + return ((long[]) array).clone(); } - if (array instanceof short[] shorts) { - return shorts.clone(); + if (type == short[].class) { + return ((short[]) array).clone(); } // else diff --git a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java index a4db2ad8553..bb2688c9490 100644 --- a/spring-core/src/main/java/org/springframework/util/ObjectUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ObjectUtils.java @@ -354,41 +354,43 @@ public abstract class ObjectUtils { } /** - * Compare the given arrays with {@code Arrays.equals}, performing an equality - * check based on the array elements rather than the array reference. + * Compare the given arrays with {@code Arrays.equals(x, y)} variants, performing + * an equality check based on the array elements rather than the array reference. * @param o1 first array to compare * @param o2 second array to compare * @return whether the given objects are equal * @see #nullSafeEquals(Object, Object) - * @see java.util.Arrays#equals + * @see java.util.Arrays */ private static boolean arrayEquals(Object o1, Object o2) { if (o1 instanceof Object[] objects1 && o2 instanceof Object[] objects2) { return Arrays.equals(objects1, objects2); } - if (o1 instanceof boolean[] booleans1 && o2 instanceof boolean[] booleans2) { - return Arrays.equals(booleans1, booleans2); + Class type1 = o1.getClass(); + Class type2 = o2.getClass(); + if (type1 == boolean[].class && type2 == boolean[].class) { + return Arrays.equals((boolean[]) o1, (boolean[]) o2); } - if (o1 instanceof byte[] bytes1 && o2 instanceof byte[] bytes2) { - return Arrays.equals(bytes1, bytes2); + if (type1 == byte[].class && type2 == byte[].class) { + return Arrays.equals((byte[]) o1, (byte[]) o2); } - if (o1 instanceof char[] chars1 && o2 instanceof char[] chars2) { - return Arrays.equals(chars1, chars2); + if (type1 == char[].class && type2 == char[].class) { + return Arrays.equals((char[]) o1, (char[]) o2); } - if (o1 instanceof double[] doubles1 && o2 instanceof double[] doubles2) { - return Arrays.equals(doubles1, doubles2); + if (type1 == double[].class && type2 == double[].class) { + return Arrays.equals((double[]) o1, (double[]) o2); } - if (o1 instanceof float[] floats1 && o2 instanceof float[] floats2) { - return Arrays.equals(floats1, floats2); + if (type1 == float[].class && type2 == float[].class) { + return Arrays.equals((float[]) o1, (float[]) o2); } - if (o1 instanceof int[] ints1 && o2 instanceof int[] ints2) { - return Arrays.equals(ints1, ints2); + if (type1 == int[].class && type2 == int[].class) { + return Arrays.equals((int[]) o1, (int[]) o2); } - if (o1 instanceof long[] longs1 && o2 instanceof long[] longs2) { - return Arrays.equals(longs1, longs2); + if (type1 == long[].class && type2 == long[].class) { + return Arrays.equals((long[]) o1, (long[]) o2); } - if (o1 instanceof short[] shorts1 && o2 instanceof short[] shorts2) { - return Arrays.equals(shorts1, shorts2); + if (type1 == short[].class && type2 == short[].class) { + return Arrays.equals((short[]) o1, (short[]) o2); } return false; } diff --git a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java index cda0bbe610b..5e82c7ee5b8 100644 --- a/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/ObjectUtilsTests.java @@ -267,6 +267,13 @@ class ObjectUtilsTests { void nullSafeEqualsWithArrays() { assertThat(ObjectUtils.nullSafeEquals(new String[] {"a", "b", "c"}, new String[] {"a", "b", "c"})).isTrue(); assertThat(ObjectUtils.nullSafeEquals(new int[] {1, 2, 3}, new int[] {1, 2, 3})).isTrue(); + assertThat(ObjectUtils.nullSafeEquals(new long[] {1, 2, 3}, new long[] {1, 2, 3})).isTrue(); + assertThat(ObjectUtils.nullSafeEquals(new short[] {1, 2, 3}, new short[] {1, 2, 3})).isTrue(); + assertThat(ObjectUtils.nullSafeEquals(new byte[] {1, 2, 3}, new byte[] {1, 2, 3})).isTrue(); + assertThat(ObjectUtils.nullSafeEquals(new float[] {1, 2, 3}, new float[] {1, 2, 3})).isTrue(); + assertThat(ObjectUtils.nullSafeEquals(new double[] {1, 2, 3}, new double[] {1, 2, 3})).isTrue(); + assertThat(ObjectUtils.nullSafeEquals(new char[] {1, 2, 3}, new char[] {1, 2, 3})).isTrue(); + assertThat(ObjectUtils.nullSafeEquals(new boolean[] {true, false, true}, new boolean[] {true, false, true})).isTrue(); } @Test