annotationType) {
+ if (this.annotatedElement.isEmpty()) {
+ // Shortcut: AnnotatedElementUtils would have to expect AnnotatedElement.getAnnotations()
+ // to return a copy of the array, whereas we can do it more efficiently here.
+ return null;
+ }
return AnnotatedElementUtils.getMergedAnnotation(this.annotatedElement, annotationType);
}
@@ -434,37 +443,51 @@ public class TypeDescriptor implements Serializable {
}
@Override
- public boolean equals(Object obj) {
- if (this == obj) {
+ public boolean equals(Object other) {
+ if (this == other) {
return true;
}
- if (!(obj instanceof TypeDescriptor)) {
+ if (!(other instanceof TypeDescriptor)) {
return false;
}
- TypeDescriptor other = (TypeDescriptor) obj;
- if (!ObjectUtils.nullSafeEquals(this.type, other.type)) {
+ TypeDescriptor otherDesc = (TypeDescriptor) other;
+ if (getType() != otherDesc.getType()) {
return false;
}
- if (getAnnotations().length != other.getAnnotations().length) {
+ if (!annotationsMatch(otherDesc)) {
return false;
}
- for (Annotation ann : getAnnotations()) {
- if (!ann.equals(other.getAnnotation(ann.annotationType()))) {
- return false;
- }
- }
if (isCollection() || isArray()) {
- return ObjectUtils.nullSafeEquals(getElementTypeDescriptor(), other.getElementTypeDescriptor());
+ return ObjectUtils.nullSafeEquals(getElementTypeDescriptor(), otherDesc.getElementTypeDescriptor());
}
else if (isMap()) {
- return ObjectUtils.nullSafeEquals(getMapKeyTypeDescriptor(), other.getMapKeyTypeDescriptor()) &&
- ObjectUtils.nullSafeEquals(getMapValueTypeDescriptor(), other.getMapValueTypeDescriptor());
+ return (ObjectUtils.nullSafeEquals(getMapKeyTypeDescriptor(), otherDesc.getMapKeyTypeDescriptor()) &&
+ ObjectUtils.nullSafeEquals(getMapValueTypeDescriptor(), otherDesc.getMapValueTypeDescriptor()));
}
else {
return true;
}
}
+ private boolean annotationsMatch(TypeDescriptor otherDesc) {
+ Annotation[] anns = getAnnotations();
+ Annotation[] otherAnns = otherDesc.getAnnotations();
+ if (anns == otherAnns) {
+ return true;
+ }
+ if (anns.length != otherAnns.length) {
+ return false;
+ }
+ if (anns.length > 0) {
+ for (int i = 0; i < anns.length; i++) {
+ if (anns[i] != otherAnns[i]) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
@Override
public int hashCode() {
return getType().hashCode();
@@ -480,6 +503,20 @@ public class TypeDescriptor implements Serializable {
return builder.toString();
}
+
+ /**
+ * Create a new type descriptor for an object.
+ * Use this factory method to introspect a source object before asking the
+ * conversion system to convert it to some another type.
+ *
If the provided object is {@code null}, returns {@code null}, else calls
+ * {@link #valueOf(Class)} to build a TypeDescriptor from the object's class.
+ * @param source the source object
+ * @return the type descriptor
+ */
+ public static TypeDescriptor forObject(Object source) {
+ return (source != null ? valueOf(source.getClass()) : null);
+ }
+
/**
* Create a new type descriptor from the given type.
*
Use this to instruct the conversion system to convert an object to a
@@ -640,19 +677,6 @@ public class TypeDescriptor implements Serializable {
return nested(new TypeDescriptor(property), nestingLevel);
}
- /**
- * Create a new type descriptor for an object.
- *
Use this factory method to introspect a source object before asking the
- * conversion system to convert it to some another type.
- *
If the provided object is {@code null}, returns {@code null}, else calls
- * {@link #valueOf(Class)} to build a TypeDescriptor from the object's class.
- * @param source the source object
- * @return the type descriptor
- */
- public static TypeDescriptor forObject(Object source) {
- return (source != null ? valueOf(source.getClass()) : null);
- }
-
private static TypeDescriptor nested(TypeDescriptor typeDescriptor, int nestingLevel) {
ResolvableType nested = typeDescriptor.resolvableType;
for (int i = 0; i < nestingLevel; i++) {
@@ -723,6 +747,10 @@ public class TypeDescriptor implements Serializable {
return getAnnotations();
}
+ public boolean isEmpty() {
+ return ObjectUtils.isEmpty(this.annotations);
+ }
+
@Override
public boolean equals(Object other) {
return (this == other || (other instanceof AnnotatedElementAdapter &&
diff --git a/spring-core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java b/spring-core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java
index 39184c2c778..9fd16139b65 100644
--- a/spring-core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java
+++ b/spring-core/src/test/java/org/springframework/core/convert/TypeDescriptorTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2015 the original author or authors.
+ * Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -533,7 +533,7 @@ public class TypeDescriptorTests {
public void elementTypePreserveContext() throws Exception {
TypeDescriptor desc = new TypeDescriptor(getClass().getField("listPreserveContext"));
assertEquals(Integer.class, desc.getElementTypeDescriptor().getElementTypeDescriptor().getType());
- List value = new ArrayList(3);
+ List value = new ArrayList<>(3);
desc = desc.elementTypeDescriptor(value);
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
assertNotNull(desc.getAnnotation(FieldAnnotation.class));
@@ -551,7 +551,7 @@ public class TypeDescriptorTests {
public void mapKeyTypePreserveContext() throws Exception {
TypeDescriptor desc = new TypeDescriptor(getClass().getField("mapPreserveContext"));
assertEquals(Integer.class, desc.getMapKeyTypeDescriptor().getElementTypeDescriptor().getType());
- List value = new ArrayList(3);
+ List value = new ArrayList<>(3);
desc = desc.getMapKeyTypeDescriptor(value);
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
assertNotNull(desc.getAnnotation(FieldAnnotation.class));
@@ -569,7 +569,7 @@ public class TypeDescriptorTests {
public void mapValueTypePreserveContext() throws Exception {
TypeDescriptor desc = new TypeDescriptor(getClass().getField("mapPreserveContext"));
assertEquals(Integer.class, desc.getMapValueTypeDescriptor().getElementTypeDescriptor().getType());
- List value = new ArrayList(3);
+ List value = new ArrayList<>(3);
desc = desc.getMapValueTypeDescriptor(value);
assertEquals(Integer.class, desc.getElementTypeDescriptor().getType());
assertNotNull(desc.getAnnotation(FieldAnnotation.class));
@@ -598,15 +598,16 @@ public class TypeDescriptorTests {
TypeDescriptor t12 = new TypeDescriptor(getClass().getField("mapField"));
assertEquals(t11, t12);
- TypeDescriptor t13 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
- TypeDescriptor t14 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
+ MethodParameter testAnnotatedMethod = new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0);
+ TypeDescriptor t13 = new TypeDescriptor(testAnnotatedMethod);
+ TypeDescriptor t14 = new TypeDescriptor(testAnnotatedMethod);
assertEquals(t13, t14);
- TypeDescriptor t15 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
+ TypeDescriptor t15 = new TypeDescriptor(testAnnotatedMethod);
TypeDescriptor t16 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethodDifferentAnnotationValue", String.class), 0));
assertNotEquals(t15, t16);
- TypeDescriptor t17 = new TypeDescriptor(new MethodParameter(getClass().getMethod("testAnnotatedMethod", String.class), 0));
+ TypeDescriptor t17 = new TypeDescriptor(testAnnotatedMethod);
TypeDescriptor t18 = new TypeDescriptor(new MethodParameter(getClass().getMethod("test5", String.class), 0));
assertNotEquals(t17, t18);
}
@@ -841,19 +842,19 @@ public class TypeDescriptorTests {
public List listOfString;
- public List> listOfListOfString = new ArrayList>();
+ public List> listOfListOfString = new ArrayList<>();
- public List listOfListOfUnknown = new ArrayList();
+ public List listOfListOfUnknown = new ArrayList<>();
public int[] intArray;
public List[] arrayOfListOfString;
- public List listField = new ArrayList();
+ public List listField = new ArrayList<>();
- public Map mapField = new HashMap();
+ public Map mapField = new HashMap<>();
- public Map> nestedMapField = new HashMap>();
+ public Map> nestedMapField = new HashMap<>();
public Map, List> fieldMap;
@@ -879,9 +880,9 @@ public class TypeDescriptorTests {
public Map isAssignableMapKeyValueTypes;
- public MultiValueMap multiValueMap = new LinkedMultiValueMap();
+ public MultiValueMap multiValueMap = new LinkedMultiValueMap<>();
- public PassDownGeneric passDownGeneric = new PassDownGeneric();
+ public PassDownGeneric passDownGeneric = new PassDownGeneric<>();
// Classes designed for test introspection