private static ResolvableType resolveVariable(TypeVariable<?> typeVariable, ResolvableType contextType) { ResolvableType resolvedType; if (contextType.hasGenerics()) { resolvedType = ResolvableType.forType(typeVariable, contextType); if (resolvedType.resolve() != null) { return resolvedType; } } ResolvableType superType = contextType.getSuperType(); if (superType != ResolvableType.NONE) { resolvedType = resolveVariable(typeVariable, superType); if (resolvedType.resolve() != null) { return resolvedType; } } for (ResolvableType ifc : contextType.getInterfaces()) { resolvedType = resolveVariable(typeVariable, ifc); if (resolvedType.resolve() != null) { return resolvedType; } } return ResolvableType.NONE; }
public static Class<?> getClass(Type type){ if(type.getClass() == Class.class){ return (Class<?>) type; } if(type instanceof ParameterizedType){ return getClass(((ParameterizedType) type).getRawType()); } if(type instanceof TypeVariable){ Type boundType = ((TypeVariable<?>) type).getBounds()[0]; return (Class<?>) boundType; } if(type instanceof WildcardType){ Type[] upperBounds = ((WildcardType) type).getUpperBounds(); if (upperBounds.length == 1) { return getClass(upperBounds[0]); } } return Object.class; }
protected static Class getTypeClass(final Type type, final Map<TypeVariable<?>, Type> typeArgs) { Type rawType = type; if (type instanceof ParameterizedType) { rawType = ((ParameterizedType) type).getRawType(); } if (rawType instanceof Class) { return (Class) rawType; } if (rawType instanceof TypeVariable) { final Type t = typeArgs.get(rawType); if (null != t) { return getTypeClass(t, typeArgs); } } // cannot resolve - default to UnknownGenericType; return UnknownGenericType.class; }
@Override public String toString() { StringBuilder sb = new StringBuilder(); Class<?> rawType = getRawType(); if (!rawType.isArray()) { sb.append(rawType.getName()); } else { sb.append(rawType.getComponentType().getName()); } TypeVariable<? extends Class<?>>[] typeParameters = rawType.getTypeParameters(); if (typeParameters.length > 0) { sb.append("<"); for (int i = 0; i < typeParameters.length; i++) { if (i > 0) { sb.append(", "); } String s = this.getParam(i).toParamString(); sb.append(s); } sb.append(">"); } if (rawType.isArray()) { sb.append("[]"); } return sb.toString(); }
private static void checkOneParameterType(ParameterizedType toCheck, Class<?> rawType, Class<?>... bounds) { System.out.println(((Class<?>) toCheck.getRawType()).getName() .equals(rawType.getName())); Type[] parameters = toCheck.getActualTypeArguments(); System.out.println(parameters.length); TypeVariable<?> parameter = (TypeVariable<?>) parameters[0]; System.out.println(parameter.getName()); Type[] actualBounds = parameter.getBounds(); for (int i = 0; i < bounds.length; i++) { System.out.println(((Class<?>) actualBounds[i]).getName().equals(bounds[i].getName())); } }
/** * Constructs a new type literal. Derives represented class from type * parameter. * * <p> * Clients create an empty anonymous subclass. Doing so embeds the type * parameter in the anonymous class's type hierarchy so we can reconstitute * it at runtime despite erasure. */ public TypeLiteral() { ParameterizedType genClass = (ParameterizedType) getClass().getGenericSuperclass(); Type[] types = genClass.getActualTypeArguments(); if (types == null || types.length == 0) { throw new RuntimeException("TypeLiteral<T> must have a specfied type <T>"); } this.type = types[0]; if (this.type instanceof GenericArrayType) throw new RuntimeException("TypeLiteral does not support GenericArrayTypes, use Injector.get(ComponentType[].class)"); if (this.type instanceof TypeVariable) throw new RuntimeException("TypeLiteral does not support TypeVariables"); if (type instanceof Class) { this.rawType = (Class<T>) this.type; } else if (type instanceof ParameterizedType) { this.rawType = (Class<T>) ((ParameterizedType) type).getRawType(); } else { this.rawType = Object.class; } }
public static Class getGenericClass(ParameterizedType parameterizedType, int i) { Object genericClass = parameterizedType.getActualTypeArguments()[i]; if (genericClass instanceof ParameterizedType) { // 处理多级泛型 return (Class) ((ParameterizedType) genericClass).getRawType(); } else if (genericClass instanceof GenericArrayType) { // 处理数组泛型 return (Class) ((GenericArrayType) genericClass).getGenericComponentType(); } else if (genericClass instanceof TypeVariable) { // 处理泛型擦拭对象 return (Class) getClass(((TypeVariable) genericClass).getBounds()[0], 0); } else { return (Class) genericClass; } }
public void testNewTypeVariable() throws Exception { TypeVariable<?> noBoundJvmType = WithTypeVariable.getTypeVariable("withoutBound"); TypeVariable<?> objectBoundJvmType = WithTypeVariable.getTypeVariable("withObjectBound"); TypeVariable<?> upperBoundJvmType = WithTypeVariable.getTypeVariable("withUpperBound"); TypeVariable<?> noBound = withBounds(noBoundJvmType); TypeVariable<?> objectBound = withBounds(objectBoundJvmType, Object.class); TypeVariable<?> upperBound = withBounds( upperBoundJvmType, Number.class, CharSequence.class); assertEqualTypeVariable(noBoundJvmType, noBound); assertEqualTypeVariable(noBoundJvmType, withBounds(noBoundJvmType, Object.class)); assertEqualTypeVariable(objectBoundJvmType, objectBound); assertEqualTypeVariable(upperBoundJvmType, upperBound); new TypeVariableEqualsTester() .addEqualityGroup(noBoundJvmType, noBound) .addEqualityGroup(objectBoundJvmType, objectBound) .addEqualityGroup(upperBoundJvmType, upperBound) .testEquals(); }
static boolean hasUnresolvableType(Type type) { if (type instanceof Class<?>) { return false; } if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; for (Type typeArgument : parameterizedType.getActualTypeArguments()) { if (hasUnresolvableType(typeArgument)) { return true; } } return false; } if (type instanceof GenericArrayType) { return hasUnresolvableType(((GenericArrayType) type).getGenericComponentType()); } if (type instanceof TypeVariable) { return true; } if (type instanceof WildcardType) { return true; } String className = type == null ? "null" : type.getClass().getName(); throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + "GenericArrayType, but <" + type + "> is of type " + className); }
public static Type getInheritGenericType(Class<?> clazz, TypeVariable<?> tv) { Type type = null; GenericDeclaration gd = tv.getGenericDeclaration(); do { type = clazz.getGenericSuperclass(); if (type == null) { return null; } if (type instanceof ParameterizedType) { ParameterizedType ptype = (ParameterizedType) type; if (ptype.getRawType() == gd) { TypeVariable<?>[] tvs = gd.getTypeParameters(); Type[] types = ptype.getActualTypeArguments(); for (int i = 0; i < tvs.length; i++) { if (tvs[i] == tv) return types[i]; } return null; } } clazz = TypeUtils.getClass(type); } while (type != null); return null; }
/** * 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) { return resolveWildcardType((WildcardType) type); } else { // if Class<?>, no resolution needed, we are done. return type; } }
private WildcardCapturer forTypeVariable(final TypeVariable<?> typeParam) { return new WildcardCapturer(id) { @Override TypeVariable<?> captureAsTypeVariable(Type[] upperBounds) { Set<Type> combined = new LinkedHashSet<>(asList(upperBounds)); // Since this is an artifically generated type variable, we don't bother checking // subtyping between declared type bound and actual type bound. So it's possible that we // may generate something like <capture#1-of ? extends Foo&SubFoo>. // Checking subtype between declared and actual type bounds // adds recursive isSubtypeOf() call and feels complicated. // There is no contract one way or another as long as isSubtypeOf() works as expected. combined.addAll(asList(typeParam.getBounds())); if (combined.size() > 1) { // Object is implicit and only useful if it's the only bound. combined.remove(Object.class); } return super.captureAsTypeVariable(combined.toArray(new Type[0])); } }; }
private static Signature createSignature(final Object input, final Type type, final Map<TypeVariable<?>, Type> typeArgs, final boolean isInput) { final Class clazz = getTypeClass(type, typeArgs); if (Tuple.class.isAssignableFrom(clazz)) { final TypeVariable[] tupleTypes = getTypeClass(type, typeArgs).getTypeParameters(); final Map<TypeVariable<?>, Type> classTypeArgs = TypeUtils.getTypeArguments(type, clazz); Collection<? extends Type> types = TypeUtils.getTypeArguments(type, clazz).values(); Class[] classes = new Class[types.size()]; int i = 0; for (final TypeVariable tupleType : tupleTypes) { classes[i++] = getTypeClass(classTypeArgs.get(tupleType), typeArgs); } return new TupleSignature(input, clazz, classes, isInput); } return new SingletonSignature(input, clazz, isInput); }
private static Type substituteTypeVariables(Map<String, Type> lookup, Type type) { if (type instanceof TypeVariable) { return translateTypeVariable(lookup, (TypeVariable) type); } if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type[] args = pType.getActualTypeArguments(); for (int i = 0; i < args.length; i++) { args[i] = substituteTypeVariables(lookup, args[i]); } return new ParameterizedTypeImpl(args, pType.getOwnerType(), pType.getRawType()); } if (type instanceof GenericArrayType) { GenericArrayType gaType = (GenericArrayType) type; return new GenericArrayTypeImpl(substituteTypeVariables(lookup, gaType.getGenericComponentType())); } return type; }
/** * Returns the generic superclass of this type or {@code null} if the type represents * {@link Object} or an interface. This method is similar but different from * {@link Class#getGenericSuperclass}. For example, {@code new TypeToken<StringArrayList>() * {}.getGenericSuperclass()} will return {@code new TypeToken<ArrayList<String>>() {}}; while * {@code StringArrayList.class.getGenericSuperclass()} will return {@code ArrayList<E>}, where * {@code E} is the type variable declared by class {@code ArrayList}. * * <p>If this type is a type variable or wildcard, its first upper bound is examined and returned * if the bound is a class or extends from a class. This means that the returned type could be a * type variable too. */ @Nullable final TypeToken<? super T> getGenericSuperclass() { if (runtimeType instanceof TypeVariable) { // First bound is always the super class, if one exists. return boundAsSuperclass(((TypeVariable<?>) runtimeType).getBounds()[0]); } if (runtimeType instanceof WildcardType) { // wildcard has one and only one upper bound. return boundAsSuperclass(((WildcardType) runtimeType).getUpperBounds()[0]); } Type superclass = getRawType().getGenericSuperclass(); if (superclass == null) { return null; } @SuppressWarnings("unchecked") // super class of T TypeToken<? super T> superToken = (TypeToken<? super T>) resolveSupertype(superclass); return superToken; }
/** * Returns the generic interfaces that this type directly {@code implements}. This method is * similar but different from {@link Class#getGenericInterfaces()}. For example, {@code new * TypeToken<List<String>>() {}.getGenericInterfaces()} will return a list that contains * {@code new TypeToken<Iterable<String>>() {}}; while {@code List.class.getGenericInterfaces()} * will return an array that contains {@code Iterable<T>}, where the {@code T} is the type * variable declared by interface {@code Iterable}. * * <p>If this type is a type variable or wildcard, its upper bounds are examined and those that * are either an interface or upper-bounded only by interfaces are returned. This means that the * returned types could include type variables too. */ final ImmutableList<TypeToken<? super T>> getGenericInterfaces() { if (runtimeType instanceof TypeVariable) { return boundsAsInterfaces(((TypeVariable<?>) runtimeType).getBounds()); } if (runtimeType instanceof WildcardType) { return boundsAsInterfaces(((WildcardType) runtimeType).getUpperBounds()); } ImmutableList.Builder<TypeToken<? super T>> builder = ImmutableList.builder(); for (Type interfaceType : getRawType().getGenericInterfaces()) { @SuppressWarnings("unchecked") // interface of T TypeToken<? super T> resolvedInterface = (TypeToken<? super T>) resolveSupertype(interfaceType); builder.add(resolvedInterface); } return builder.build(); }
/** * Returns the generic form of {@code superclass}. For example, if this is * {@code ArrayList<String>}, {@code Iterable<String>} is returned given the input * {@code Iterable.class}. */ public final TypeToken<? super T> getSupertype(Class<? super T> superclass) { checkArgument( this.someRawTypeIsSubclassOf(superclass), "%s is not a super class of %s", superclass, this); if (runtimeType instanceof TypeVariable) { return getSupertypeFromUpperBounds(superclass, ((TypeVariable<?>) runtimeType).getBounds()); } if (runtimeType instanceof WildcardType) { return getSupertypeFromUpperBounds(superclass, ((WildcardType) runtimeType).getUpperBounds()); } if (superclass.isArray()) { return getArraySupertype(superclass); } @SuppressWarnings("unchecked") // resolved supertype TypeToken<? super T> supertype = (TypeToken<? super T>) resolveSupertype(toGenericType(superclass).runtimeType); return supertype; }
static Type resolveTypeVariable(Type context, Class<?> contextRawType, TypeVariable<?> unknown) { Class<?> declaredByRaw = declaringClassOf(unknown); // we can't reduce this further if (declaredByRaw == null) { return unknown; } Type declaredBy = getGenericSupertype(context, contextRawType, declaredByRaw); if (declaredBy instanceof ParameterizedType) { int index = indexOf(declaredByRaw.getTypeParameters(), unknown); return ((ParameterizedType) declaredBy).getActualTypeArguments()[index]; } return unknown; }
public ParameterizedTypeWrapper substitute(TypeVariable<?> typeVariable, TypeWrapper type) { TypeWrapper[] newArguments = new TypeWrapper[actualTypeArguments.length]; for (int i = 0; i < newArguments.length; i++) { TypeWrapper argument = actualTypeArguments[i]; if (argument instanceof TypeVariableTypeWrapper) { TypeVariableTypeWrapper candidate = (TypeVariableTypeWrapper) argument; if (candidate.getName().equals(typeVariable.getName())) { newArguments[i] = type; continue; } } newArguments[i] = argument; } return new ParameterizedTypeWrapper(newArguments, rawType, ownerType); }
/** * If the class is parameterized, such as {@link java.util.ArrayList ArrayList}, this returns * {@code ArrayList<E>}. */ @Override Type getGenericReturnType() { Class<?> declaringClass = getDeclaringClass(); TypeVariable<?>[] typeParams = declaringClass.getTypeParameters(); if (typeParams.length > 0) { return Types.newParameterizedType(declaringClass, typeParams); } else { return declaringClass; } }
public <T> void testCaptureTypeParameter() throws Exception { TypeVariable<?> variable = new TypeParameter<T>() {}.typeVariable; TypeVariable<?> expected = TypeParameterTest.class .getDeclaredMethod("testCaptureTypeParameter") .getTypeParameters()[0]; assertEquals(expected, variable); }
/** * Returns true if {@code type} is a {@code TypeVariable} with the same name and declared by the * same {@code GenericDeclaration}. */ boolean equalsType(Type type) { if (type instanceof TypeVariable) { return equalsTypeVariable((TypeVariable<?>) type); } else { return false; } }
static Class<?> getRawType(Type type) { if (type == null) throw new NullPointerException("type == null"); if (type instanceof Class<?>) { // Type is a normal class. return (Class<?>) type; } if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; // I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but // suspects some pathological case related to nested classes exists. Type rawType = parameterizedType.getRawType(); if (!(rawType instanceof Class)) throw new IllegalArgumentException(); return (Class<?>) rawType; } if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType) type).getGenericComponentType(); return Array.newInstance(getRawType(componentType), 0).getClass(); } if (type instanceof TypeVariable) { // We could use the variable's bounds, but that won't work if there are multiple. Having a raw // type that's more general than necessary is okay. return Object.class; } if (type instanceof WildcardType) { return getRawType(((WildcardType) type).getUpperBounds()[0]); } throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName()); }
/** * Returns the declaring class of {@code typeVariable}, or {@code null} if it was not declared by * a class. */ private static Class<?> declaringClassOf(TypeVariable<?> typeVariable) { GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration(); return genericDeclaration instanceof Class ? (Class<?>) genericDeclaration : null; }
/** * {@inheritDoc} * * {@code [<E>]} will be returned for ArrayList's constructor. When both the class and the * constructor have type parameters, the class parameters are prepended before those of the * constructor's. This is an arbitrary rule since no existing language spec mandates one way or * the other. From the declaration syntax, the class type parameter appears first, but the call * syntax may show up in opposite order such as {@code new <A>Foo<B>()}. */ @Override public final TypeVariable<?>[] getTypeParameters() { TypeVariable<?>[] declaredByClass = getDeclaringClass().getTypeParameters(); TypeVariable<?>[] declaredByConstructor = constructor.getTypeParameters(); TypeVariable<?>[] result = new TypeVariable<?>[declaredByClass.length + declaredByConstructor.length]; System.arraycopy(declaredByClass, 0, result, 0, declaredByClass.length); System.arraycopy( declaredByConstructor, 0, result, declaredByClass.length, declaredByConstructor.length); return result; }
public static Class<?> getRawType(Type type) { if (type instanceof Class<?>) { // type is a normal class. return (Class<?>) type; } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; // I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but // suspects some pathological case related to nested classes exists. Type rawType = parameterizedType.getRawType(); return (Class<?>) rawType; } else if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType) type).getGenericComponentType(); return Array.newInstance(getRawType(componentType), 0).getClass(); } else if (type instanceof TypeVariable) { // We could use the variable's bounds, but that won't work if there are multiple. having a raw // type that's more general than necessary is okay. return Object.class; } else if (type instanceof WildcardType) { return getRawType(((WildcardType) type).getUpperBounds()[0]); } else { String className = type == null ? "null" : type.getClass().getName(); throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + "GenericArrayType, but <" + type + "> is of type " + className); } }
@SuppressWarnings("unchecked") public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType) type).getGenericComponentType(); if (componentType instanceof TypeVariable) { TypeVariable<?> componentVar = (TypeVariable<?>) componentType; componentType = componentVar.getBounds()[0]; } List<Object> list = new ArrayList<Object>(); parser.parseArray(componentType, list); Class<?> componentClass; if (componentType instanceof Class) { componentClass = (Class<?>) componentType; Object[] array = (Object[]) Array.newInstance(componentClass, list.size()); list.toArray(array); return (T) array; } else { return (T) list.toArray(); } } if (type instanceof Class && type != Object.class && type != Serializable.class) { return (T) parser.parseObject(type); } return (T) parser.parse(fieldName); }
/** * Returns the formal type parameters of this generic declaration. * @return the formal type parameters of this generic declaration */ public TypeVariable<?>[] getTypeParameters() { TypeVariable<?>[] value = typeParameters; if (value == null) { value = computeTypeParameters(); typeParameters = value; } return value.clone(); }
final Type resolve(final TypeVariable<?> var) { final TypeTable unguarded = this; TypeTable guarded = new TypeTable() { @Override public Type resolveInternal(TypeVariable<?> intermediateVar, TypeTable forDependent) { if (intermediateVar.getGenericDeclaration().equals(var.getGenericDeclaration())) { return intermediateVar; } return unguarded.resolveInternal(intermediateVar, forDependent); } }; return resolveInternal(var, guarded); }
@Override public boolean equals(Object o) { if (o instanceof TypeVariable && o.getClass() == TypeVariableImpl.class) { TypeVariable<?> that = (TypeVariable<?>) o; GenericDeclaration thatDecl = that.getGenericDeclaration(); String thatName = that.getName(); return Objects.equals(genericDeclaration, thatDecl) && Objects.equals(name, thatName); } else return false; }
private static Type getInheritGenericType(Class<?> clazz, Type type, TypeVariable<?> tv) { GenericDeclaration gd = tv.getGenericDeclaration(); Class<?> class_gd = null; if (gd instanceof Class) { class_gd = (Class<?>) tv.getGenericDeclaration(); } Type[] arguments = null; if (class_gd == clazz) { if (type instanceof ParameterizedType) { ParameterizedType ptype = (ParameterizedType) type; arguments = ptype.getActualTypeArguments(); } } else { for (Class<?> c = clazz; c != null && c != Object.class && c != class_gd; c = c.getSuperclass()) { Type superType = c.getGenericSuperclass(); if (superType instanceof ParameterizedType) { ParameterizedType p_superType = (ParameterizedType) superType; Type[] p_superType_args = p_superType.getActualTypeArguments(); getArgument(p_superType_args, c.getTypeParameters(), arguments); arguments = p_superType_args; } } } if (arguments == null) { return null; } Type actualType = null; TypeVariable<?>[] typeVariables = class_gd.getTypeParameters(); for (int j = 0; j < typeVariables.length; ++j) { if (tv.equals(typeVariables[j])) { actualType = arguments[j]; break; } } return actualType; }
static Class<?> getRawType(Type type) { checkNotNull(type, "type == null"); if (type instanceof Class<?>) { // Type is a normal class. return (Class<?>) type; } if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; // I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but // suspects some pathological case related to nested classes exists. Type rawType = parameterizedType.getRawType(); if (!(rawType instanceof Class)) throw new IllegalArgumentException(); return (Class<?>) rawType; } if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType) type).getGenericComponentType(); return Array.newInstance(getRawType(componentType), 0).getClass(); } if (type instanceof TypeVariable) { // We could use the variable's bounds, but that won't work if there are multiple. Having a raw // type that's more general than necessary is okay. return Object.class; } if (type instanceof WildcardType) { return getRawType(((WildcardType) type).getUpperBounds()[0]); } throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName()); }
private void validateConstructorArguments() { TypeVariable<?>[] formals = rawType.getTypeParameters(); // check correct arity of actual type args if (formals.length != actualTypeArguments.length){ throw new MalformedParameterizedTypeException(); } for (int i = 0; i < actualTypeArguments.length; i++) { // check actuals against formals' bounds } }
private Class getRawType(Type type) { if (type instanceof Class) { return (Class)type; } else if (type instanceof java.lang.reflect.ParameterizedType) { return (Class)(((java.lang.reflect.ParameterizedType)type).getRawType()); } else if (type instanceof TypeVariable) { return Object.class; } else if (type instanceof WildcardType) { return getRawType(((WildcardType)type).getUpperBounds()[0]); } else if (type instanceof GenericArrayType) { return Array.newInstance(getRawType(((GenericArrayType)type).getGenericComponentType()), 0).getClass(); } else { throw new RuntimeException("Invalid type passed: " + type); } }
public void testGetSubtype_genericSubtypeOfGenericTypeWithFewerParameters() { TypeToken<List<String>> supertype = new TypeToken<List<String>>() {}; TypeToken<MySpecialList<String, ?>> subtype = new TypeToken<MySpecialList<String, ?>>() {}; assertTrue(subtype.isSubtypeOf(supertype)); ParameterizedType actualSubtype = (ParameterizedType) supertype.getSubtype(subtype.getRawType()).getType(); assertEquals(MySpecialList.class, actualSubtype.getRawType()); assertThat(actualSubtype.getActualTypeArguments()[0]).isEqualTo(String.class); assertThat(actualSubtype.getActualTypeArguments()[1]).isInstanceOf(TypeVariable.class); assertTrue(TypeToken.of(actualSubtype).isSubtypeOf(supertype)); }
public static void main(String[] args) throws NoSuchMethodException, SecurityException, NoSuchFieldException { for (TypeVariable<Class<Generic>> var : Generic.class.getTypeParameters()) { System.out.println(var.getName()); Type bound = var.getBounds()[0]; System.out.println(((Class<?>) bound).getName().equals(AA.class.getName())); } Field f = Generic.class.getField("f"); ParameterizedType fieldType = (java.lang.reflect.ParameterizedType)f.getGenericType(); checkOneParameterType(fieldType, Generic.class, AA.class); ParameterizedType methodReturnType = (ParameterizedType) Generic.class.getMethod("get").getGenericReturnType(); checkOneParameterType(methodReturnType, Generic.class, AA.class); }
private void validateConstructorArguments() { TypeVariable/*<?>*/[] formals = rawType.getTypeParameters(); // check correct arity of actual type args if (formals.length != actualTypeArguments.length) { throw new MalformedParameterizedTypeException(); } /* for (int i = 0; i < actualTypeArguments.length; i++) { // check actuals against formals' bounds } */ }
@SuppressWarnings({"unchecked", "rawtypes"}) public <T> T deserialize(Object object, Type type) { JSONArray jsonArray; if (object instanceof JSONArray) { jsonArray = (JSONArray) object; } else { jsonArray = new JSONArray(object); } Class componentClass = null; Type componentType = null; if (type instanceof GenericArrayType) { componentType = ((GenericArrayType) type).getGenericComponentType(); if (componentType instanceof TypeVariable) { TypeVariable<?> componentVar = (TypeVariable<?>) componentType; componentType = componentVar.getBounds()[0]; } if (componentType instanceof Class<?>) { componentClass = (Class<?>) componentType; } } else { Class clazz = (Class) type; componentType = componentClass = clazz.getComponentType(); } int size = jsonArray.size(); Object array = Array.newInstance(componentClass, size); for (int i = 0; i < size; i++) { Object value = jsonArray.get(i); Deserializer deserializer = JSONParser.getDeserializer(componentClass); Array.set(array, i, deserializer.deserialize(value, componentType)); } return (T) array; }