diff --git a/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileAnnotationDelegate.java b/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileAnnotationDelegate.java index d5ce6e21941..1990fefa39e 100644 --- a/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileAnnotationDelegate.java +++ b/spring-core/src/main/java24/org/springframework/core/type/classreading/ClassFileAnnotationDelegate.java @@ -27,7 +27,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.jspecify.annotations.Nullable; @@ -108,27 +107,13 @@ abstract class ClassFileAnnotationDelegate { } private static Object parseArrayValue(String className, @Nullable ClassLoader classLoader, AnnotationValue.OfArray arrayValue) { - if (arrayValue.values().isEmpty()) { - return new Object[0]; - } - Stream stream = arrayValue.values().stream(); - switch (arrayValue.values().getFirst()) { - case AnnotationValue.OfInt _ -> { - return stream.map(AnnotationValue.OfInt.class::cast).mapToInt(AnnotationValue.OfInt::intValue).toArray(); - } - case AnnotationValue.OfDouble _ -> { - return stream.map(AnnotationValue.OfDouble.class::cast).mapToDouble(AnnotationValue.OfDouble::doubleValue).toArray(); - } - case AnnotationValue.OfLong _ -> { - return stream.map(AnnotationValue.OfLong.class::cast).mapToLong(AnnotationValue.OfLong::longValue).toArray(); - } - default -> { - Class arrayElementType = resolveArrayElementType(arrayValue.values(), classLoader); - return stream - .map(rawValue -> readAnnotationValue(className, rawValue, classLoader)) - .toArray(length -> (Object[]) Array.newInstance(arrayElementType, length)); - } + List values = arrayValue.values(); + Class arrayElementType = (values.isEmpty() ? Object.class : resolveArrayElementType(values, classLoader)); + Object array = Array.newInstance(arrayElementType, values.size()); + for (int i = 0; i < values.size(); i++) { + Array.set(array, i, readAnnotationValue(className, values.get(i), classLoader)); } + return array; } @SuppressWarnings("unchecked") @@ -143,24 +128,21 @@ abstract class ClassFileAnnotationDelegate { } private static Class resolveArrayElementType(List values, @Nullable ClassLoader classLoader) { - AnnotationValue firstValue = values.getFirst(); - switch (firstValue) { - case AnnotationValue.OfConstant constantValue -> { - return constantValue.resolvedValue().getClass(); - } - case AnnotationValue.OfAnnotation _ -> { - return MergedAnnotation.class; - } - case AnnotationValue.OfClass _ -> { - return String.class; - } - case AnnotationValue.OfEnum enumValue -> { - return loadEnumClass(enumValue, classLoader); - } - default -> { - return Object.class; - } - } + return switch (values.getFirst()) { + case AnnotationValue.OfByte _ -> byte.class; + case AnnotationValue.OfChar _ -> char.class; + case AnnotationValue.OfDouble _ -> double.class; + case AnnotationValue.OfFloat _ -> float.class; + case AnnotationValue.OfInt _ -> int.class; + case AnnotationValue.OfLong _ -> long.class; + case AnnotationValue.OfShort _ -> short.class; + case AnnotationValue.OfBoolean _ -> boolean.class; + case AnnotationValue.OfString _ -> String.class; + case AnnotationValue.OfAnnotation _ -> MergedAnnotation.class; + case AnnotationValue.OfClass _ -> String.class; + case AnnotationValue.OfEnum enumValue -> loadEnumClass(enumValue, classLoader); + case AnnotationValue.OfArray _ -> Object.class; + }; } diff --git a/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java b/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java index 48681542e4a..1db8fe2e1d4 100644 --- a/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java +++ b/spring-core/src/test/java/org/springframework/core/type/AbstractAnnotationMetadataTests.java @@ -302,12 +302,17 @@ public abstract class AbstractAnnotationMetadataTests { void getComplexAttributeTypesReturnsAll() { MultiValueMap attributes = get(WithComplexAttributeTypes.class).getAllAnnotationAttributes(ComplexAttributes.class.getName()); - assertThat(attributes).containsOnlyKeys("names", "count", "types", "subAnnotation"); + assertThat(attributes).containsOnlyKeys("names", "count", "types", "bytes", "floats", "shorts", "chars", "booleans", "subAnnotation"); assertThat(attributes.get("names")).hasSize(1); assertThat(attributes.get("names").get(0)).isEqualTo(new String[]{"first", "second"}); assertThat(attributes.get("count").get(0)).isEqualTo(new TestEnum[]{TestEnum.ONE, TestEnum.TWO}); assertThat(attributes.get("types").get(0)).isEqualTo(new Class[]{TestEnum.class}); assertThat(attributes.get("subAnnotation")).hasSize(1); + assertThat(attributes.get("bytes").get(0)).isEqualTo(new byte[]{1, 2}); + assertThat(attributes.get("floats").get(0)).isEqualTo(new float[]{1.0f, 2.0f}); + assertThat(attributes.get("shorts").get(0)).isEqualTo(new short[]{1, 2}); + assertThat(attributes.get("chars").get(0)).isEqualTo(new char[]{'a', 'b'}); + assertThat(attributes.get("booleans").get(0)).isEqualTo(new boolean[]{true, false}); } @Test @@ -324,7 +329,7 @@ public abstract class AbstractAnnotationMetadataTests { void getAnnotationAttributeIntType() { MultiValueMap attributes = get(WithIntType.class).getAllAnnotationAttributes(ComplexAttributes.class.getName()); - assertThat(attributes).containsOnlyKeys("names", "count", "types", "subAnnotation"); + assertThat(attributes).containsOnlyKeys("names", "count", "types", "bytes", "floats", "shorts", "chars", "booleans", "subAnnotation"); assertThat(attributes.get("types").get(0)).isEqualTo(new Class[]{int.class}); } @@ -471,13 +476,15 @@ public abstract class AbstractAnnotationMetadataTests { @ComplexAttributes(names = {"first", "second"}, count = {TestEnum.ONE, TestEnum.TWO}, - types = {TestEnum.class}, subAnnotation = @SubAnnotation(name="spring")) + types = {TestEnum.class}, subAnnotation = @SubAnnotation(name="spring"), bytes = {1, 2}, + floats = {1.0f, 2.0f}, shorts = {1, 2}, chars = {'a', 'b'}, booleans = {true, false}) @Metadata(mv = {42}) public static class WithComplexAttributeTypes { } @ComplexAttributes(names = "void", count = TestEnum.ONE, types = int.class, - subAnnotation = @SubAnnotation(name="spring")) + subAnnotation = @SubAnnotation(name="spring"), bytes = {1, 2}, + floats = {1.0f, 2.0f}, shorts = {1, 2}, chars = {'a', 'b'}, booleans = {true, false}) public static class WithIntType { } @@ -491,6 +498,16 @@ public abstract class AbstractAnnotationMetadataTests { Class[] types(); + byte[] bytes(); + + float[] floats(); + + short[] shorts(); + + char[] chars(); + + boolean[] booleans(); + SubAnnotation subAnnotation(); }