Browse Source

Polishing (includes nullable declaration for internal type array)

7.0.x
Juergen Hoeller 2 days ago
parent
commit
f0472ea1c0
  1. 47
      spring-core/src/main/java/org/springframework/util/TypeUtils.java

47
spring-core/src/main/java/org/springframework/util/TypeUtils.java

@ -38,15 +38,16 @@ import org.springframework.lang.Contract; @@ -38,15 +38,16 @@ import org.springframework.lang.Contract;
*/
public abstract class TypeUtils {
private static final Type[] IMPLICIT_LOWER_BOUNDS = { null };
private static final @Nullable Type[] IMPLICIT_LOWER_BOUNDS = { null };
private static final Type[] IMPLICIT_UPPER_BOUNDS = { Object.class };
/**
* Check if the right-hand side type may be assigned to the left-hand side
* type following the Java generics rules.
* @param lhsType the target type (left-hand side (LHS) type)
* @param rhsType the value type (right-hand side (RHS) type) that should
* @param lhsType the target type (left-hand side type)
* @param rhsType the value type (right-hand side type) that should
* be assigned to the target type
* @return {@code true} if {@code rhsType} is assignable to {@code lhsType}
* @see ClassUtils#isAssignable(Class, Class)
@ -55,37 +56,34 @@ public abstract class TypeUtils { @@ -55,37 +56,34 @@ public abstract class TypeUtils {
Assert.notNull(lhsType, "Left-hand side type must not be null");
Assert.notNull(rhsType, "Right-hand side type must not be null");
// all types are assignable to themselves and to class Object
// All types are assignable to themselves and to class Object.
if (lhsType.equals(rhsType) || Object.class == lhsType) {
return true;
}
if (lhsType instanceof Class<?> lhsClass) {
// just comparing two classes
// Just comparing two classes...
if (rhsType instanceof Class<?> rhsClass) {
return ClassUtils.isAssignable(lhsClass, rhsClass);
}
if (rhsType instanceof ParameterizedType rhsParameterizedType) {
Type rhsRaw = rhsParameterizedType.getRawType();
// a parameterized type is always assignable to its raw class type
// A parameterized type is always assignable to its raw class type.
if (rhsRaw instanceof Class<?> rhRawClass) {
return ClassUtils.isAssignable(lhsClass, rhRawClass);
}
}
else if (lhsClass.isArray() && rhsType instanceof GenericArrayType rhsGenericArrayType) {
Type rhsComponent = rhsGenericArrayType.getGenericComponentType();
return isAssignable(lhsClass.componentType(), rhsComponent);
}
}
// parameterized types are only assignable to other parameterized types and class types
// Parameterized types are only assignable to other parameterized types and class types.
if (lhsType instanceof ParameterizedType lhsParameterizedType) {
if (rhsType instanceof Class<?> rhsClass) {
Type lhsRaw = lhsParameterizedType.getRawType();
if (lhsRaw instanceof Class<?> lhsClass) {
return ClassUtils.isAssignable(lhsClass, rhsClass);
}
@ -97,7 +95,6 @@ public abstract class TypeUtils { @@ -97,7 +95,6 @@ public abstract class TypeUtils {
if (lhsType instanceof GenericArrayType lhsGenericArrayType) {
Type lhsComponent = lhsGenericArrayType.getGenericComponentType();
if (rhsType instanceof Class<?> rhsClass && rhsClass.isArray()) {
return isAssignable(lhsComponent, rhsClass.componentType());
}
@ -122,7 +119,6 @@ public abstract class TypeUtils { @@ -122,7 +119,6 @@ public abstract class TypeUtils {
Type[] lhsTypeArguments = lhsType.getActualTypeArguments();
Type[] rhsTypeArguments = rhsType.getActualTypeArguments();
if (lhsTypeArguments.length != rhsTypeArguments.length) {
return false;
}
@ -130,7 +126,6 @@ public abstract class TypeUtils { @@ -130,7 +126,6 @@ public abstract class TypeUtils {
for (int size = lhsTypeArguments.length, i = 0; i < size; ++i) {
Type lhsArg = lhsTypeArguments[i];
Type rhsArg = rhsTypeArguments[i];
if (!lhsArg.equals(rhsArg) &&
!(lhsArg instanceof WildcardType wildcardType && isAssignable(wildcardType, rhsArg))) {
return false;
@ -141,17 +136,14 @@ public abstract class TypeUtils { @@ -141,17 +136,14 @@ public abstract class TypeUtils {
}
private static boolean isAssignable(WildcardType lhsType, Type rhsType) {
Type[] lUpperBounds = getUpperBounds(lhsType);
Type[] lLowerBounds = getLowerBounds(lhsType);
@Nullable Type[] lUpperBounds = getUpperBounds(lhsType);
@Nullable Type[] lLowerBounds = getLowerBounds(lhsType);
if (rhsType instanceof WildcardType rhsWcType) {
// both the upper and lower bounds of the right-hand side must be
// completely enclosed in the upper and lower bounds of the left-
// hand side.
Type[] rUpperBounds = getUpperBounds(rhsWcType);
Type[] rLowerBounds = getLowerBounds(rhsWcType);
// Both the upper and lower bounds of the right-hand side must be
// completely enclosed in the upper and lower bounds of the left-hand side.
@Nullable Type[] rUpperBounds = getUpperBounds(rhsWcType);
@Nullable Type[] rLowerBounds = getLowerBounds(rhsWcType);
for (Type lBound : lUpperBounds) {
for (Type rBound : rUpperBounds) {
@ -159,7 +151,6 @@ public abstract class TypeUtils { @@ -159,7 +151,6 @@ public abstract class TypeUtils {
return false;
}
}
for (Type rBound : rLowerBounds) {
if (!isAssignableBound(lBound, rBound)) {
return false;
@ -173,7 +164,6 @@ public abstract class TypeUtils { @@ -173,7 +164,6 @@ public abstract class TypeUtils {
return false;
}
}
for (Type rBound : rLowerBounds) {
if (!isAssignableBound(rBound, lBound)) {
return false;
@ -187,7 +177,6 @@ public abstract class TypeUtils { @@ -187,7 +177,6 @@ public abstract class TypeUtils {
return false;
}
}
for (Type lBound : lLowerBounds) {
if (!isAssignableBound(rhsType, lBound)) {
return false;
@ -198,17 +187,15 @@ public abstract class TypeUtils { @@ -198,17 +187,15 @@ public abstract class TypeUtils {
return true;
}
private static Type[] getLowerBounds(WildcardType wildcardType) {
private static @Nullable Type[] getLowerBounds(WildcardType wildcardType) {
Type[] lowerBounds = wildcardType.getLowerBounds();
// supply the implicit lower bound if none are specified
// Supply the implicit lower bound if none are specified.
return (lowerBounds.length == 0 ? IMPLICIT_LOWER_BOUNDS : lowerBounds);
}
private static Type[] getUpperBounds(WildcardType wildcardType) {
Type[] upperBounds = wildcardType.getUpperBounds();
// supply the implicit upper bound if none are specified
// Supply the implicit upper bound if none are specified.
return (upperBounds.length == 0 ? IMPLICIT_UPPER_BOUNDS : upperBounds);
}

Loading…
Cancel
Save