diff --git a/spring-core/src/main/java/org/springframework/core/convert/TypeDescriptor.java b/spring-core/src/main/java/org/springframework/core/convert/TypeDescriptor.java index 1eb90c823bab..df1a829ba381 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/TypeDescriptor.java +++ b/spring-core/src/main/java/org/springframework/core/convert/TypeDescriptor.java @@ -30,6 +30,7 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -52,8 +53,6 @@ @SuppressWarnings("serial") public class TypeDescriptor implements Serializable { - private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; - private static final Map, TypeDescriptor> commonTypesCache = new HashMap<>(32); private static final Class[] CACHED_COMMON_TYPES = { @@ -84,7 +83,7 @@ public class TypeDescriptor implements Serializable { public TypeDescriptor(MethodParameter methodParameter) { this.resolvableType = ResolvableType.forMethodParameter(methodParameter); this.type = this.resolvableType.resolve(methodParameter.getNestedParameterType()); - this.annotatedElement = new AnnotatedElementAdapter(methodParameter.getParameterIndex() == -1 ? + this.annotatedElement = AnnotatedElementAdapter.from(methodParameter.getParameterIndex() == -1 ? methodParameter.getMethodAnnotations() : methodParameter.getParameterAnnotations()); } @@ -96,7 +95,7 @@ public TypeDescriptor(MethodParameter methodParameter) { public TypeDescriptor(Field field) { this.resolvableType = ResolvableType.forField(field); this.type = this.resolvableType.resolve(field.getType()); - this.annotatedElement = new AnnotatedElementAdapter(field.getAnnotations()); + this.annotatedElement = AnnotatedElementAdapter.from(field.getAnnotations()); } /** @@ -109,7 +108,7 @@ public TypeDescriptor(Property property) { Assert.notNull(property, "Property must not be null"); this.resolvableType = ResolvableType.forMethodParameter(property.getMethodParameter()); this.type = this.resolvableType.resolve(property.getType()); - this.annotatedElement = new AnnotatedElementAdapter(property.getAnnotations()); + this.annotatedElement = AnnotatedElementAdapter.from(property.getAnnotations()); } /** @@ -125,7 +124,7 @@ public TypeDescriptor(Property property) { public TypeDescriptor(ResolvableType resolvableType, @Nullable Class type, @Nullable Annotation[] annotations) { this.resolvableType = resolvableType; this.type = (type != null ? type : resolvableType.toClass()); - this.annotatedElement = new AnnotatedElementAdapter(annotations); + this.annotatedElement = AnnotatedElementAdapter.from(annotations); } @@ -742,15 +741,23 @@ public static TypeDescriptor nested(Property property, int nestingLevel) { * @see AnnotatedElementUtils#isAnnotated(AnnotatedElement, Class) * @see AnnotatedElementUtils#getMergedAnnotation(AnnotatedElement, Class) */ - private class AnnotatedElementAdapter implements AnnotatedElement, Serializable { + private static final class AnnotatedElementAdapter implements AnnotatedElement, Serializable { + private static final AnnotatedElementAdapter EMPTY = new AnnotatedElementAdapter(new Annotation[0]); - @Nullable + @NonNull private final Annotation[] annotations; - public AnnotatedElementAdapter(@Nullable Annotation[] annotations) { + private AnnotatedElementAdapter(@NonNull Annotation[] annotations) { this.annotations = annotations; } + private static AnnotatedElementAdapter from(@Nullable Annotation[] annotations) { + if (annotations == null || annotations.length == 0) { + return EMPTY; + } + return new AnnotatedElementAdapter(annotations); + } + @Override public boolean isAnnotationPresent(Class annotationClass) { for (Annotation annotation : getAnnotations()) { @@ -775,7 +782,7 @@ public T getAnnotation(Class annotationClass) { @Override public Annotation[] getAnnotations() { - return (this.annotations != null ? this.annotations.clone() : EMPTY_ANNOTATION_ARRAY); + return isEmpty() ? this.annotations : this.annotations.clone(); } @Override @@ -784,7 +791,7 @@ public Annotation[] getDeclaredAnnotations() { } public boolean isEmpty() { - return ObjectUtils.isEmpty(this.annotations); + return this.annotations.length == 0; } @Override @@ -800,7 +807,7 @@ public int hashCode() { @Override public String toString() { - return TypeDescriptor.this.toString(); + return "{AnnotatedElementAdapter annotations=" + Arrays.toString(this.annotations) + "}"; } }