static String toString(WildcardType wt) { final boolean isSuper = wt.getLowerBounds().length > 0; return String.format( "? %s %s", isSuper ? "super" : "extends", isSuper ? toString(wt.getLowerBounds()) : toString(wt.getLowerBounds())); }
private String nameFor(WildcardType wild) { if ((wild.getLowerBounds().length != 0)) { return nameFor(wild.getLowerBounds()[0]); } else { return nameFor(wild.getUpperBounds()[0]); } }
/** Returns true if {@code a} and {@code b} are equal. */ public static boolean equals(Type a, Type b) { if (a == b) { // also handles (a == null && b == null) return true; } else if (a instanceof Class) { // Class already specifies equals(). return a.equals(b); } else if (a instanceof ParameterizedType) { if (!(b instanceof ParameterizedType)) { return false; } // TODO: save a .clone() call ParameterizedType pa = (ParameterizedType) a; ParameterizedType pb = (ParameterizedType) b; return equal(pa.getOwnerType(), pb.getOwnerType()) && pa.getRawType().equals(pb.getRawType()) && Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments()); } else if (a instanceof GenericArrayType) { if (!(b instanceof GenericArrayType)) { return false; } GenericArrayType ga = (GenericArrayType) a; GenericArrayType gb = (GenericArrayType) b; return equals(ga.getGenericComponentType(), gb.getGenericComponentType()); } else if (a instanceof WildcardType) { if (!(b instanceof WildcardType)) { return false; } WildcardType wa = (WildcardType) a; WildcardType wb = (WildcardType) b; return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds()) && Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds()); } else if (a instanceof TypeVariable) { if (!(b instanceof TypeVariable)) { return false; } TypeVariable<?> va = (TypeVariable<?>) a; TypeVariable<?> vb = (TypeVariable<?>) b; return va.getGenericDeclaration() == vb.getGenericDeclaration() && va.getName().equals(vb.getName()); } else { // This isn't a type we support. Could be a generic array type, // wildcard type, etc. return false; } }
private void visitType(java.lang.reflect.Type type, StringBuilder builder) { if (type instanceof Class) { Class<?> cl = (Class<?>) type; if (cl.isPrimitive()) { builder.append(Type.getType(cl).getDescriptor()); } else { if (cl.isArray()) { builder.append(cl.getName().replace('.', '/')); } else { builder.append('L'); builder.append(cl.getName().replace('.', '/')); builder.append(';'); } } } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; visitNested(parameterizedType.getRawType(), builder); builder.append('<'); for (java.lang.reflect.Type param : parameterizedType.getActualTypeArguments()) { visitType(param, builder); } builder.append(">;"); } else if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; if (wildcardType.getUpperBounds().length == 1 && wildcardType.getUpperBounds()[0].equals(Object.class)) { if (wildcardType.getLowerBounds().length == 0) { builder.append('*'); return; } } else { for (java.lang.reflect.Type upperType : wildcardType.getUpperBounds()) { builder.append('+'); visitType(upperType, builder); } } for (java.lang.reflect.Type lowerType : wildcardType.getLowerBounds()) { builder.append('-'); visitType(lowerType, builder); } } else if (type instanceof TypeVariable) { TypeVariable<?> typeVar = (TypeVariable) type; builder.append('T'); builder.append(typeVar.getName()); builder.append(';'); } else if (type instanceof GenericArrayType) { GenericArrayType arrayType = (GenericArrayType) type; builder.append('['); visitType(arrayType.getGenericComponentType(), builder); } else { throw new IllegalArgumentException( String.format("Cannot generate signature for %s.", type)); } }
/** * Converts a Type into a jdiff compatible String. The returned types from this function should * match the same Strings that jdiff is providing to us. * * @param type the type to convert. * @return the jdiff formatted string. */ private static String typeToString(Type type) { if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; StringBuffer sb = new StringBuffer(); sb.append(typeToString(pt.getRawType())); sb.append("<"); int elementNum = 0; Type[] types = pt.getActualTypeArguments(); for (Type t : types) { sb.append(typeToString(t)); if (++elementNum < types.length) { sb.append(", "); } } sb.append(">"); return sb.toString(); } else if (type instanceof TypeVariable) { return ((TypeVariable<?>) type).getName(); } else if (type instanceof Class) { return ((Class<?>) type).getCanonicalName(); } else if (type instanceof GenericArrayType) { String typeName = typeToString(((GenericArrayType) type).getGenericComponentType()); return typeName + "[]"; } else if (type instanceof WildcardType) { WildcardType wt = (WildcardType) type; Type[] lowerBounds = wt.getLowerBounds(); if (lowerBounds.length == 0) { String name = "? extends " + concatWildcardTypes(wt.getUpperBounds()); // Special case for ? if (name.equals("? extends java.lang.Object")) { return "?"; } else { return name; } } else { String name = concatWildcardTypes(wt.getUpperBounds()) + " super " + concatWildcardTypes(wt.getLowerBounds()); // Another special case for ? name = name.replace("java.lang.Object", "?"); return name; } } else { throw new RuntimeException("Got an unknown java.lang.Type"); } }
@Override public boolean equals(Object obj) { if (!(obj instanceof WildcardType)) return false; WildcardType other = (WildcardType) obj; return Arrays.equals(lowerBounds, other.getLowerBounds()) && Arrays.equals(upperBounds, other.getUpperBounds()); }
@Nullable private static TypeWrapper wrap(Type type) { if (type == null) { return null; } else if (type instanceof Class) { return new ClassTypeWrapper((Class<?>) type); } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; return new ParameterizedTypeWrapper( toWrappers(parameterizedType.getActualTypeArguments()), (ClassTypeWrapper) wrap(parameterizedType.getRawType()), wrap(parameterizedType.getOwnerType())); } else if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; return new WildcardTypeWrapper( toWrappers(wildcardType.getUpperBounds()), toWrappers(wildcardType.getLowerBounds()), type.hashCode()); } else if (type instanceof TypeVariable) { TypeVariable<?> typeVariable = (TypeVariable<?>) type; return new TypeVariableTypeWrapper( typeVariable.getName(), toWrappers(typeVariable.getBounds()), type.hashCode()); } else if (type instanceof GenericArrayType) { GenericArrayType genericArrayType = (GenericArrayType) type; return new GenericArrayTypeWrapper( wrap(genericArrayType.getGenericComponentType()), type.hashCode()); } else { throw new IllegalArgumentException("cannot wrap type of type " + type.getClass()); } }
/** 获取一个Type类型实际对应的Class */ @SuppressWarnings("rawtypes") public static Class<?> getTypeClass(Type type) { Class<?> clazz = null; if (type instanceof Class<?>) { clazz = (Class<?>) type; } else if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; clazz = (Class<?>) pt.getRawType(); } else if (type instanceof GenericArrayType) { GenericArrayType gat = (GenericArrayType) type; Class<?> typeClass = getTypeClass(gat.getGenericComponentType()); return Array.newInstance(typeClass, 0).getClass(); } else if (type instanceof TypeVariable) { TypeVariable tv = (TypeVariable) type; Type[] ts = tv.getBounds(); if (ts != null && ts.length > 0) return getTypeClass(ts[0]); } else if (type instanceof WildcardType) { WildcardType wt = (WildcardType) type; Type[] t_low = wt.getLowerBounds(); // 取其下界 if (t_low.length > 0) return getTypeClass(t_low[0]); Type[] t_up = wt.getUpperBounds(); // 没有下界?取其上界 return getTypeClass(t_up[0]); // 最起码有Object作为上界 } return clazz; }
public boolean equals(Object o) { if (o instanceof WildcardType) { WildcardType wt = (WildcardType) o; return Arrays.equals(upperBounds, wt.getUpperBounds()) && Arrays.equals(lowerBounds, wt.getLowerBounds()); } else return false; }
public static Type[] getImplicitLowerBounds(WildcardType paramWildcardType) { Type[] arrayOfType = paramWildcardType.getLowerBounds(); if (arrayOfType.length == 0) { arrayOfType = new Type[1]; arrayOfType[0] = null; } return arrayOfType; }
public boolean equals(Object var1) { if (!(var1 instanceof WildcardType)) { return false; } else { WildcardType var2 = (WildcardType) var1; return this.lowerBounds.equals(Arrays.asList(var2.getLowerBounds())) && this.upperBounds.equals(Arrays.asList(var2.getUpperBounds())); } }
@Override public boolean equals(Object obj) { if (obj instanceof WildcardType) { WildcardType that = (WildcardType) obj; return lowerBounds.equals(Arrays.asList(that.getLowerBounds())) && upperBounds.equals(Arrays.asList(that.getUpperBounds())); } return false; }
public static boolean matches(Type type1, Type type2) { if (type1 instanceof Class<?>) { Class<?> clazz = (Class<?>) type1; if (matches(clazz, EMPTY_TYPES, type2)) { return true; } } if (type1 instanceof ParameterizedType) { ParameterizedType parameterizedType1 = (ParameterizedType) type1; if (parameterizedType1.getRawType() instanceof Class<?>) { if (matches( (Class<?>) parameterizedType1.getRawType(), parameterizedType1.getActualTypeArguments(), type2)) { return true; } } } if (type1 instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type1; if (isTypeBounded(type2, wildcardType.getLowerBounds(), wildcardType.getUpperBounds())) { return true; } } if (type2 instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type2; if (isTypeBounded(type1, wildcardType.getUpperBounds(), wildcardType.getLowerBounds())) { return true; } } if (type1 instanceof TypeVariable<?>) { TypeVariable<?> typeVariable = (TypeVariable<?>) type1; if (isTypeBounded(type2, EMPTY_TYPES, typeVariable.getBounds())) { return true; } } if (type2 instanceof TypeVariable<?>) { TypeVariable<?> typeVariable = (TypeVariable<?>) type2; if (isTypeBounded(type1, typeVariable.getBounds(), EMPTY_TYPES)) { return true; } } return false; }
/** * @param type - something like List<? super T>, List<<? extends T>, List<? extends T & * Comparable<? super T>> * @param containingType - the shallowest type in the hierarchy where type is defined. * @return the passed type if nothing to resolve or a copy of the type with the upper and lower * bounds resolved. */ private static WildcardType resolve(WildcardType type, Type containingType) { // Use a copy because we're going to modify them. final Type[] upper = type.getUpperBounds().clone(); final Type[] lower = type.getLowerBounds().clone(); boolean modified = resolve(upper, containingType); modified = modified || resolve(lower, containingType); return modified ? create(upper, lower) : type; }
private static boolean isWildcardTypeAssignable(WildcardType supertype, Type type) { for (Type upperBound : supertype.getUpperBounds()) { if (!isAssignable(upperBound, type)) { return false; } } for (Type lowerBound : supertype.getLowerBounds()) { if (!isAssignable(type, lowerBound)) { return false; } } return true; }
/** Returns the array type of {@code componentType}. */ static Type newArrayType(Type componentType) { if (componentType instanceof WildcardType) { WildcardType wildcard = (WildcardType) componentType; Type[] lowerBounds = wildcard.getLowerBounds(); checkArgument(lowerBounds.length <= 1, "Wildcard cannot have more than one lower bounds."); if (lowerBounds.length == 1) { return supertypeOf(newArrayType(lowerBounds[0])); } else { Type[] upperBounds = wildcard.getUpperBounds(); checkArgument(upperBounds.length == 1, "Wildcard should have only one upper bound."); return subtypeOf(newArrayType(upperBounds[0])); } } return JavaVersion.CURRENT.newArrayType(componentType); }
static Type newArrayType(Type var0) { if (var0 instanceof WildcardType) { WildcardType var1 = (WildcardType) var0; Type[] var2 = var1.getLowerBounds(); Preconditions.checkArgument( var2.length <= 1, "Wildcard cannot have more than one lower bounds."); if (var2.length == 1) { return supertypeOf(newArrayType(var2[0])); } else { Type[] var3 = var1.getUpperBounds(); Preconditions.checkArgument(var3.length == 1, "Wildcard should have only one upper bound."); return subtypeOf(newArrayType(var3[0])); } } else { return Types.JavaVersion.CURRENT.newArrayType(var0); } }
/** * Resolves all type variables in {@code type} and all downstream types and returns a * corresponding type with type variables resolved. */ public Type resolveType(Type type) { checkNotNull(type); if (type instanceof TypeVariable) { return typeTable.resolve((TypeVariable<?>) type); } else if (type instanceof ParameterizedType) { return resolveParameterizedType((ParameterizedType) type); } else if (type instanceof GenericArrayType) { return resolveGenericArrayType((GenericArrayType) type); } else if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; return new Types.WildcardTypeImpl( resolveTypes(wildcardType.getLowerBounds()), resolveTypes(wildcardType.getUpperBounds())); } else { // if Class<?>, no resolution needed, we are done. return type; } }
/** * Returns raw class for given <code>type</code> when implementation class is known and it makes * difference. * * @see #resolveVariable(java.lang.reflect.TypeVariable, Class) */ public static Class<?> getRawType(Type type, Class implClass) { if (type instanceof Class) { return (Class) type; } if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; return getRawType(pType.getRawType(), implClass); } if (type instanceof WildcardType) { WildcardType wType = (WildcardType) type; Type[] lowerTypes = wType.getLowerBounds(); if (lowerTypes.length > 0) { return getRawType(lowerTypes[0], implClass); } Type[] upperTypes = wType.getUpperBounds(); if (upperTypes.length != 0) { return getRawType(upperTypes[0], implClass); } return Object.class; } if (type instanceof GenericArrayType) { Type genericComponentType = ((GenericArrayType) type).getGenericComponentType(); Class<?> rawType = getRawType(genericComponentType, implClass); // this is sort of stupid, but there seems no other way (consider don't creating new instances // each time)... return Array.newInstance(rawType, 0).getClass(); } if (type instanceof TypeVariable) { TypeVariable<?> varType = (TypeVariable<?>) type; if (implClass != null) { Type resolvedType = resolveVariable(varType, implClass); if (resolvedType != null) { return getRawType(resolvedType, null); } } Type[] boundsTypes = varType.getBounds(); if (boundsTypes.length == 0) { return Object.class; } return getRawType(boundsTypes[0], implClass); } return null; }
/** * Creates {@link TypeInformation} for the given {@link Type}. * * @param fieldType the field type * @return the type information */ @SuppressWarnings({"rawtypes", "unchecked"}) protected TypeInformation<?> createInfo(Type fieldType) { if (fieldType.equals(this.type)) { return this; } if (fieldType instanceof Class) { return new ClassTypeInformation((Class<?>) fieldType); } Map<TypeVariable, Type> variableMap = GenericTypeResolver.getTypeVariableMap(resolveType(fieldType)); if (fieldType instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) fieldType; return new ParameterizedTypeInformation(parameterizedType, this); } if (fieldType instanceof TypeVariable) { TypeVariable<?> variable = (TypeVariable<?>) fieldType; return new TypeVariableTypeInformation(variable, type, this, variableMap); } if (fieldType instanceof GenericArrayType) { return new GenericArrayTypeInformation((GenericArrayType) fieldType, this); } if (fieldType instanceof WildcardType) { WildcardType wildcardType = (WildcardType) fieldType; Type[] bounds = wildcardType.getLowerBounds(); if (bounds.length > 0) { return createInfo(bounds[0]); } bounds = wildcardType.getUpperBounds(); if (bounds.length > 0) { return createInfo(bounds[0]); } } throw new IllegalArgumentException(); }
private ClassNode configureWildcardType(WildcardType wildcardType) { ClassNode base = ClassHelper.makeWithoutCaching("?"); base.setRedirect(ClassHelper.OBJECT_TYPE); // TODO: more than one lower bound for wildcards? ClassNode[] lowers = configureTypes(wildcardType.getLowerBounds()); ClassNode lower = null; // TODO: is it safe to remove this? What was the original intention? if (lower != null) lower = lowers[0]; ClassNode[] upper = configureTypes(wildcardType.getUpperBounds()); GenericsType t = new GenericsType(base, upper, lower); t.setWildcard(true); ClassNode ref = ClassHelper.makeWithoutCaching(Object.class, false); ref.setGenericsTypes(new GenericsType[] {t}); return ref; }
public static Class<?> getActualType(Type genericType, final int pos) { if (genericType == null) return null; if (!ParameterizedType.class.isAssignableFrom(genericType.getClass())) { if (genericType instanceof TypeVariable) genericType = getType(((TypeVariable<?>) genericType).getBounds(), pos); else if (genericType instanceof WildcardType) { final WildcardType wildcardType = (WildcardType) genericType; Type[] bounds = wildcardType.getLowerBounds(); if (bounds.length == 0) bounds = wildcardType.getUpperBounds(); genericType = getType(bounds, pos); } final Class<?> cls = (Class<?>) genericType; return cls.isArray() ? cls.getComponentType() : cls; } final ParameterizedType paramType = (ParameterizedType) genericType; final Type t = getType(paramType.getActualTypeArguments(), pos); return t instanceof Class ? (Class<?>) t : getActualType(t, pos); }
/** * Returns a type that is functionally equal but not necessarily equal according to {@link * Object#equals(Object) Object.equals()}. The returned type is {@link Serializable}. */ public 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) { ParameterizedType p = (ParameterizedType) type; return new ParameterizedTypeImpl( p.getOwnerType(), p.getRawType(), p.getActualTypeArguments()); } else if (type instanceof GenericArrayType) { GenericArrayType g = (GenericArrayType) type; return new GenericArrayTypeImpl(g.getGenericComponentType()); } else if (type instanceof WildcardType) { WildcardType w = (WildcardType) type; return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds()); } else { // type is either serializable as-is or unsupported return type; } }
Type capture(Type type) { checkNotNull(type); if (type instanceof Class) { return type; } if (type instanceof TypeVariable) { return type; } if (type instanceof GenericArrayType) { GenericArrayType arrayType = (GenericArrayType) type; return Types.newArrayType(capture(arrayType.getGenericComponentType())); } if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; return Types.newParameterizedTypeWithOwner( captureNullable(parameterizedType.getOwnerType()), (Class<?>) parameterizedType.getRawType(), capture(parameterizedType.getActualTypeArguments())); } if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; Type[] lowerBounds = wildcardType.getLowerBounds(); if (lowerBounds.length == 0) { // ? extends something changes to capture-of Type[] upperBounds = wildcardType.getUpperBounds(); String name = "capture#" + id.incrementAndGet() + "-of ? extends " + Joiner.on('&').join(upperBounds); return Types.newTypeVariable(WildcardCapturer.class, name, wildcardType.getUpperBounds()); } else { // TODO(benyu): handle ? super T somehow. return type; } } throw new AssertionError("must have been one of the known types"); }
/** 得到实际Type类型对应的Class */ public static Class<?> asClass(Type actualType) { if (actualType instanceof Class) return (Class<?>) actualType; if (actualType instanceof ParameterizedType) { final Type rawType = ((ParameterizedType) actualType).getRawType(); // The sun implementation returns getRawType as Class<?>, but there is room in the interface // for it to be // some other Type. We'll assume it's a Class. // TODO: consider logging or throwing our own exception for that day when "something else" // causes some confusion return (Class) rawType; } if (actualType instanceof GenericArrayType) { final Type type = ((GenericArrayType) actualType).getGenericComponentType(); return Array.newInstance(asClass(type), 0).getClass(); } if (actualType instanceof TypeVariable) { // Support for List<T extends Number> // There is always at least one bound. If no bound is specified in the source then it will be // Object.class return asClass(((TypeVariable) actualType).getBounds()[0]); } if (actualType instanceof WildcardType) { final WildcardType wildcardType = (WildcardType) actualType; final Type[] bounds = wildcardType.getLowerBounds(); if (bounds != null && bounds.length > 0) { return asClass(bounds[0]); } // If there is no lower bounds then the only thing that makes sense is Object. return Object.class; } throw new RuntimeException(String.format("Unable to convert %s to Class.", actualType)); }
private static void typeToString(StringBuilder sb, Type type, Set<Type> visited) { if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; final Class<?> rawType = (Class<?>) parameterizedType.getRawType(); sb.append(rawType.getName()); boolean first = true; for (Type typeArg : parameterizedType.getActualTypeArguments()) { if (first) { first = false; } else { sb.append(", "); } sb.append('<'); typeToString(sb, typeArg, visited); sb.append('>'); } } else if (type instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type; sb.append('?'); // According to // JLS(http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.5.1): // - Lower and upper can't coexist: (for instance, this is not allowed: <? extends // List<String> & super MyInterface>) // - Multiple bounds are not supported (for instance, this is not allowed: <? extends // List<String> & MyInterface>) final Type bound; if (wildcardType.getLowerBounds().length != 0) { sb.append(" super "); bound = wildcardType.getLowerBounds()[0]; } else { sb.append(" extends "); bound = wildcardType.getUpperBounds()[0]; } typeToString(sb, bound, visited); } else if (type instanceof TypeVariable<?>) { TypeVariable<?> typeVariable = (TypeVariable<?>) type; sb.append(typeVariable.getName()); // prevent cycles in case: <T extends List<T>> if (!visited.contains(type)) { visited.add(type); sb.append(" extends "); boolean first = true; for (Type bound : typeVariable.getBounds()) { if (first) { first = false; } else { sb.append(" & "); } typeToString(sb, bound, visited); } visited.remove(type); } } else if (type instanceof GenericArrayType) { GenericArrayType genericArrayType = (GenericArrayType) type; typeToString(genericArrayType.getGenericComponentType()); sb.append(genericArrayType.getGenericComponentType()); sb.append("[]"); } else if (type instanceof Class) { Class<?> typeClass = (Class<?>) type; sb.append(typeClass.getName()); } else { throw new IllegalArgumentException("Unsupported type: " + type); } }
public static Type resolve(Type context, Class<?> contextRawType, Type toResolve) { // this implementation is made a little more complicated in an attempt // to avoid object-creation while (true) { if (toResolve instanceof TypeVariable) { TypeVariable<?> typeVariable = (TypeVariable<?>) toResolve; toResolve = resolveTypeVariable(context, contextRawType, typeVariable); if (toResolve == typeVariable) { return toResolve; } } else if (toResolve instanceof Class && ((Class<?>) toResolve).isArray()) { Class<?> original = (Class<?>) toResolve; Type componentType = original.getComponentType(); Type newComponentType = resolve(context, contextRawType, componentType); return componentType == newComponentType ? original : arrayOf(newComponentType); } else if (toResolve instanceof GenericArrayType) { GenericArrayType original = (GenericArrayType) toResolve; Type componentType = original.getGenericComponentType(); Type newComponentType = resolve(context, contextRawType, componentType); return componentType == newComponentType ? original : arrayOf(newComponentType); } else if (toResolve instanceof ParameterizedType) { ParameterizedType original = (ParameterizedType) toResolve; Type ownerType = original.getOwnerType(); Type newOwnerType = resolve(context, contextRawType, ownerType); boolean changed = newOwnerType != ownerType; Type[] args = original.getActualTypeArguments(); for (int t = 0, length = args.length; t < length; t++) { Type resolvedTypeArgument = resolve(context, contextRawType, args[t]); if (resolvedTypeArgument != args[t]) { if (!changed) { args = args.clone(); changed = true; } args[t] = resolvedTypeArgument; } } return changed ? newParameterizedTypeWithOwner(newOwnerType, original.getRawType(), args) : original; } else if (toResolve instanceof WildcardType) { WildcardType original = (WildcardType) toResolve; Type[] originalLowerBound = original.getLowerBounds(); Type[] originalUpperBound = original.getUpperBounds(); if (originalLowerBound.length == 1) { Type lowerBound = resolve(context, contextRawType, originalLowerBound[0]); if (lowerBound != originalLowerBound[0]) { return supertypeOf(lowerBound); } } else if (originalUpperBound.length == 1) { Type upperBound = resolve(context, contextRawType, originalUpperBound[0]); if (upperBound != originalUpperBound[0]) { return subtypeOf(upperBound); } } return original; } else { return toResolve; } } }
static TypeName get(WildcardType wildcardName, Map<Type, TypeVariableName> map) { return new WildcardTypeName( list(wildcardName.getUpperBounds(), map), list(wildcardName.getLowerBounds(), map)); }
/** * Returns an array containing a single value of <code>null</code> if {@link * WildcardType#getLowerBounds()} returns an empty array. Otherwise, it returns the result of * <code>WildcardType.getLowerBounds()</code>. * * @param wildcardType the subject wildcard type * @return a non-empty array containing the lower bounds of the wildcard type. */ public static Type[] getImplicitLowerBounds(WildcardType wildcardType) { Type[] bounds = wildcardType.getLowerBounds(); return bounds.length == 0 ? new Type[] {null} : bounds; }
public void testWithGenericLowerBoundInWildcard() throws Exception { WildcardType wildcardType = (WildcardType) new WithGenericBound<String>() {}.getTargetType("withWildcardLowerBound"); assertEquals(String.class, wildcardType.getLowerBounds()[0]); }