/** * Returns the type from super class's type parameter in {@link MoreTypes#canonicalize(Type) * canonical form}. */ static Type getSuperclassTypeParameter(Class<?> subclass) { Type superclass = subclass.getGenericSuperclass(); if (superclass instanceof Class) { throw new RuntimeException("Missing type parameter."); } ParameterizedType parameterized = (ParameterizedType) superclass; return MoreTypes.canonicalize(parameterized.getActualTypeArguments()[0]); }
/** Unsafe. Constructs a type literal manually. */ @SuppressWarnings("unchecked") TypeLiteral(Type type) { this.type = MoreTypes.canonicalize(type); this.rawType = (Class<? super T>) MoreTypes.getRawType(this.type); this.hashCode = this.type.hashCode(); }
/** * Constructs a new type literal. Derives represented class from type parameter. * * <p> * * <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. */ @SuppressWarnings("unchecked") protected TypeLiteral() { this.type = getSuperclassTypeParameter(getClass()); this.rawType = (Class<? super T>) MoreTypes.getRawType(type); this.hashCode = type.hashCode(); }
/** * Returns the generic form of {@code supertype}. For example, if this is {@code * ArrayList<String>}, this returns {@code Iterable<String>} given the input {@code * Iterable.class}. * * @param supertype a superclass of, or interface implemented by, this. * @since 2.0 */ public TypeLiteral<?> getSupertype(Class<?> supertype) { Assert.checkArgument( supertype.isAssignableFrom(rawType), "%s is not a supertype of %s", supertype, this.type); return resolve(MoreTypes.getGenericSupertype(type, rawType, supertype)); }
Type resolveType(Type toResolve) { // this implementation is made a little more complicated in an attempt to avoid object-creation while (true) { if (toResolve instanceof TypeVariable) { TypeVariable original = (TypeVariable) toResolve; toResolve = MoreTypes.resolveTypeVariable(type, rawType, original); if (toResolve == original) { return toResolve; } } else if (toResolve instanceof GenericArrayType) { GenericArrayType original = (GenericArrayType) toResolve; Type componentType = original.getGenericComponentType(); Type newComponentType = resolveType(componentType); return componentType == newComponentType ? original : Types.arrayOf(newComponentType); } else if (toResolve instanceof ParameterizedType) { ParameterizedType original = (ParameterizedType) toResolve; Type ownerType = original.getOwnerType(); Type newOwnerType = resolveType(ownerType); boolean changed = newOwnerType != ownerType; Type[] args = original.getActualTypeArguments(); for (int t = 0, length = args.length; t < length; t++) { Type resolvedTypeArgument = resolveType(args[t]); if (resolvedTypeArgument != args[t]) { if (!changed) { args = args.clone(); changed = true; } args[t] = resolvedTypeArgument; } } return changed ? Types.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 = resolveType(originalLowerBound[0]); if (lowerBound != originalLowerBound[0]) { return Types.supertypeOf(lowerBound); } } else if (originalUpperBound.length == 1) { Type upperBound = resolveType(originalUpperBound[0]); if (upperBound != originalUpperBound[0]) { return Types.subtypeOf(upperBound); } } return original; } else { return toResolve; } } }
@Override public final String toString() { return MoreTypes.typeToString(type); }
@Override public final boolean equals(Object o) { return o instanceof TypeLiteral<?> && MoreTypes.equals(type, ((TypeLiteral) o).type); }