/** * Returns a type that is functionally equal but not necessarily equal according to {@link * Object#equals(Object) Object.equals()}. */ static Type canonicalize(Type type) { if (type instanceof Class) { Class<?> c = (Class<?>) type; return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c; } else if (type instanceof ParameterizedType) { if (type instanceof ParameterizedTypeImpl) return type; ParameterizedType p = (ParameterizedType) type; return new ParameterizedTypeImpl(p.getOwnerType(), p.getRawType(), p.getActualTypeArguments()); } else if (type instanceof GenericArrayType) { if (type instanceof GenericArrayTypeImpl) return type; GenericArrayType g = (GenericArrayType) type; return new GenericArrayTypeImpl(g.getGenericComponentType()); } else if (type instanceof WildcardType) { if (type instanceof WildcardTypeImpl) return type; WildcardType w = (WildcardType) type; return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds()); } else { return type; // This type is unsupported! } }
/** * Returns a type that represents an unknown supertype of {@code bound}. For example, if {@code * bound} is {@code String.class}, this returns {@code ? super String}. */ public static WildcardType supertypeOf(Type bound) { return new WildcardTypeImpl(new Type[] { Object.class }, new Type[] { bound }); }
/** * Returns a type that represents an unknown type that extends {@code bound}. For example, if * {@code bound} is {@code CharSequence.class}, this returns {@code ? extends CharSequence}. If * {@code bound} is {@code Object.class}, this returns {@code ?}, which is shorthand for {@code * ? extends Object}. */ public static WildcardType subtypeOf(Type bound) { return new WildcardTypeImpl(new Type[] { bound }, EMPTY_TYPE_ARRAY); }