FileDocCategorySizeDatePackage
TypeReference.javaAPI DocAndroid 5.1 API15557Thu Mar 12 22:22:10 GMT 2015android.hardware.camera2.utils

TypeReference

public abstract class TypeReference extends Object
Super type token; allows capturing generic types at runtime by forcing them to be reified.

Usage example:

{@code
// using anonymous classes (preferred)
TypeReference<Integer> intToken = new TypeReference<Integer>() {{ }};

// using named classes
class IntTypeReference extends TypeReference<Integer> {...}
TypeReference<Integer> intToken = new IntTypeReference();
}

Unlike the reference implementation, this bans nested TypeVariables; that is all dynamic types must equal to the static types.

See http://gafter.blogspot.com/2007/05/limitation-of-super-type-tokens.html for more details.

Fields Summary
private final Type
mType
private final int
mHash
Constructors Summary
protected TypeReference()
Create a new type reference for {@code T}.

throws
IllegalArgumentException if {@code T}'s actual type contains a type variable
see
TypeReference

        ParameterizedType thisType = (ParameterizedType)getClass().getGenericSuperclass();

        // extract the "T" from TypeReference<T>
        mType = thisType.getActualTypeArguments()[0];

        /*
         * Prohibit type references with type variables such as
         *
         *    class GenericListToken<T> extends TypeReference<List<T>>
         *
         * Since the "T" there is not known without an instance of T, type equality would
         * consider *all* Lists equal regardless of T. Allowing this would defeat
         * some of the type safety of a type reference.
         */
        if (containsTypeVariable(mType)) {
            throw new IllegalArgumentException(
                    "Including a type variable in a type reference is not allowed");
        }
        mHash = mType.hashCode();
    
private TypeReference(Type type)

        mType = type;
        if (containsTypeVariable(mType)) {
            throw new IllegalArgumentException(
                    "Including a type variable in a type reference is not allowed");
        }
        mHash = mType.hashCode();
    
Methods Summary
public static booleancontainsTypeVariable(java.lang.reflect.Type type)
Check if the {@code type} contains a {@link TypeVariable} recursively.

Intuitively, a type variable is a type in a type expression that refers to a generic type which is not known at the definition of the expression (commonly seen when type parameters are used, e.g. {@code class Foo}).

See http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.4 for a more formal definition of a type variable

.

param
type a type object ({@code null} is allowed)
return
{@code true} if there were nested type variables; {@code false} otherwise

        if (type == null) {
            // Trivially false
            return false;
        } else if (type instanceof TypeVariable<?>) {
            /*
             * T -> trivially true
             */
            return true;
        } else if (type instanceof Class<?>) {
            /*
             * class Foo -> no type variable
             * class Foo<T> - has a type variable
             *
             * This also covers the case of class Foo<T> extends ... / implements ...
             * since everything on the right hand side would either include a type variable T
             * or have no type variables.
             */
            Class<?> klass = (Class<?>)type;

            // Empty array => class is not generic
            if (klass.getTypeParameters().length != 0) {
                return true;
            } else {
                // Does the outer class(es) contain any type variables?

                /*
                 * class Outer<T> {
                 *   class Inner {
                 *      T field;
                 *   }
                 * }
                 *
                 * In this case 'Inner' has no type parameters itself, but it still has a type
                 * variable as part of the type definition.
                 */
                return containsTypeVariable(klass.getDeclaringClass());
            }
        } else if (type instanceof ParameterizedType) {
            /*
             * This is the "Foo<T1, T2, T3, ... Tn>" in the scope of a
             *
             *      // no type variables here, T1-Tn are known at this definition
             *      class X extends Foo<T1, T2, T3, ... Tn>
             *
             *      // T1 is a type variable, T2-Tn are known at this definition
             *      class X<T1> extends Foo<T1, T2, T3, ... Tn>
             */
            ParameterizedType p = (ParameterizedType) type;

            // This needs to be recursively checked
            for (Type arg : p.getActualTypeArguments()) {
                if (containsTypeVariable(arg)) {
                    return true;
                }
            }

            return false;
        } else if (type instanceof WildcardType) {
            WildcardType wild = (WildcardType) type;

            /*
             * This is is the "?" inside of a
             *
             *       Foo<?> --> unbounded; trivially no type variables
             *       Foo<? super T> --> lower bound; does T have a type variable?
             *       Foo<? extends T> --> upper bound; does T have a type variable?
             */

            /*
             *  According to JLS 4.5.1
             *  (http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.5.1):
             *
             *  - More than 1 lower/upper bound is illegal
             *  - Both a lower and upper bound is illegal
             *
             *  However, we use this 'array OR array' approach for readability
             */
            return containsTypeVariable(wild.getLowerBounds()) ||
                    containsTypeVariable(wild.getUpperBounds());
        }

        return false;
    
private static booleancontainsTypeVariable(java.lang.reflect.Type[] typeArray)
Check if any of the elements in this array contained a type variable.

Empty and null arrays trivially have no type variables.

param
typeArray an array ({@code null} is ok) of types
return
true if any elements contained a type variable; false otherwise

        if (typeArray == null) {
            return false;
        }

        for (Type type : typeArray) {
            if (containsTypeVariable(type)) {
                return true;
            }
        }

        return false;
    
public static android.hardware.camera2.utils.TypeReferencecreateSpecializedTypeReference(java.lang.Class klass)
Create a specialized type reference from a dynamic class instance, bypassing the standard compile-time checks.

As with a regular type reference, the {@code klass} must not contain any type variables.

param
klass a non-{@code null} {@link Class} instance
return
a type reference which captures {@code T} at runtime
throws
IllegalArgumentException if {@code T} had any type variables

        return new SpecializedTypeReference<T>(klass);
    
public static android.hardware.camera2.utils.TypeReferencecreateSpecializedTypeReference(java.lang.reflect.Type type)
Create a specialized type reference from a dynamic {@link Type} instance, bypassing the standard compile-time checks.

As with a regular type reference, the {@code type} must not contain any type variables.

param
type a non-{@code null} {@link Type} instance
return
a type reference which captures {@code T} at runtime
throws
IllegalArgumentException if {@code type} had any type variables

        return new SpecializedBaseTypeReference(type);
    
public booleanequals(java.lang.Object o)
Compare two objects for equality.

A TypeReference is only equal to another TypeReference if their captured type {@code T} is also equal.

        // Note that this comparison could inaccurately return true when comparing types
        // with nested type variables; therefore we ban type variables in the constructor.
        return o instanceof TypeReference<?> && mType.equals(((TypeReference<?>)o).mType);
    
private static final java.lang.ClassgetArrayClass(java.lang.Class componentType)

        return Array.newInstance(componentType, 0).getClass();
    
public android.hardware.camera2.utils.TypeReferencegetComponentType()
Get the component type, e.g. {@code T} from {@code T[]}.

return
component type, or {@code null} if {@code T} is not an array

        Type componentType = getComponentType(mType);

        return (componentType != null) ?
                createSpecializedTypeReference(componentType) :
                null;
    
private static java.lang.reflect.TypegetComponentType(java.lang.reflect.Type type)

        checkNotNull(type, "type must not be null");

        if (type instanceof Class<?>) {
            return ((Class<?>) type).getComponentType();
        } else if (type instanceof ParameterizedType) {
            return null;
        } else if (type instanceof GenericArrayType) {
            return ((GenericArrayType)type).getGenericComponentType();
        } else if (type instanceof WildcardType) {
            // Should be at most 1 upper bound, but treat it like an array for simplicity
            throw new UnsupportedOperationException("TODO: support wild card components");
        } else if (type instanceof TypeVariable) {
            throw new AssertionError("Type variables are not allowed in type references");
        } else {
            // Impossible
            throw new AssertionError("Unhandled branch to get component type for type " + type);
        }
    
public final java.lang.ClassgetRawType()
Returns the raw type of T.

  • If T is a Class itself, T itself is returned.
  • If T is a ParameterizedType, the raw type of the parameterized type is returned.
  • If T is a GenericArrayType, the returned type is the corresponding array class. For example: {@code List[]} => {@code List[]}.
  • If T is a type variable or a wildcard type, the raw type of the first upper bound is returned. For example: {@code } => {@code Foo}.

return
the raw type of {@code T}

        return (Class<? super T>)getRawType(mType);
    
private static final java.lang.ClassgetRawType(java.lang.reflect.Type type)

        if (type == null) {
            throw new NullPointerException("type must not be null");
        }

        if (type instanceof Class<?>) {
            return (Class<?>)type;
        } else if (type instanceof ParameterizedType) {
            return (Class<?>)(((ParameterizedType)type).getRawType());
        } else if (type instanceof GenericArrayType) {
            return getArrayClass(getRawType(((GenericArrayType)type).getGenericComponentType()));
        } else if (type instanceof WildcardType) {
            // Should be at most 1 upper bound, but treat it like an array for simplicity
            return getRawType(((WildcardType) type).getUpperBounds());
        } else if (type instanceof TypeVariable) {
            throw new AssertionError("Type variables are not allowed in type references");
        } else {
            // Impossible
            throw new AssertionError("Unhandled branch to get raw type for type " + type);
        }
    
private static final java.lang.ClassgetRawType(java.lang.reflect.Type[] types)

        if (types == null) {
            return null;
        }

        for (Type type : types) {
            Class<?> klass = getRawType(type);
            if (klass !=  null) {
                return klass;
            }
        }

        return null;
    
public java.lang.reflect.TypegetType()
Return the dynamic {@link Type} corresponding to the captured type {@code T}.

        return mType;
    
public inthashCode()
{@inheritDoc}

        return mHash;
    
public java.lang.StringtoString()
{@inheritDoc}

        StringBuilder builder = new StringBuilder();
        builder.append("TypeReference<");
        toString(getType(), builder);
        builder.append(">");

        return builder.toString();
    
private static voidtoString(java.lang.reflect.Type type, java.lang.StringBuilder out)

        if (type == null) {
            return;
        } else if (type instanceof TypeVariable<?>) {
            // T
            out.append(((TypeVariable<?>)type).getName());
        } else if (type instanceof Class<?>) {
            Class<?> klass = (Class<?>)type;

            out.append(klass.getName());
            toString(klass.getTypeParameters(), out);
        } else if (type instanceof ParameterizedType) {
             // "Foo<T1, T2, T3, ... Tn>"
            ParameterizedType p = (ParameterizedType) type;

            out.append(((Class<?>)p.getRawType()).getName());
            toString(p.getActualTypeArguments(), out);
        } else if (type instanceof GenericArrayType) {
            GenericArrayType gat = (GenericArrayType)type;

            toString(gat.getGenericComponentType(), out);
            out.append("[]");
        } else { // WildcardType, BoundedType
            // TODO:
            out.append(type.toString());
        }
    
private static voidtoString(java.lang.reflect.Type[] types, java.lang.StringBuilder out)

        if (types == null) {
            return;
        } else if (types.length == 0) {
            return;
        }

        out.append("<");

        for (int i = 0; i < types.length; ++i) {
            toString(types[i], out);
            if (i != types.length - 1) {
                out.append(", ");
            }
        }

        out.append(">");