/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson.reflect;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.HashMap;
import java.util.Map;
/**
* Represents a generic type {@code T}.
*
* You can use this class to get the generic type for a class. For example,
* to get the generic type for Collection<Foo>, you can use:
*
* Type typeOfCollectionOfFoo = new TypeToken<Collection<Foo>>(){}.getType()
*
*
*
Assumes {@code Type} implements {@code equals()} and {@code hashCode()}
* as a value (as opposed to identity) comparison.
*
* Also implements {@link #isAssignableFrom(Type)} to check type-safe
* assignability.
*
* @author Bob Lee
* @author Sven Mawson
*/
public abstract class TypeToken {
final Class super T> rawType;
final Type type;
/**
* Constructs a new type token. Derives represented class from type
* parameter.
*
*
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.
*
*
For example:
*
* {@literal TypeToken> t = new TypeToken>}(){}
*
*/
@SuppressWarnings("unchecked")
protected TypeToken() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class super T>) getRawType(type);
}
/**
* Unsafe. Constructs a type token manually.
*/
@SuppressWarnings({"unchecked"})
private TypeToken(Type type) {
this.rawType = (Class super T>) getRawType(nonNull(type, "type"));
this.type = type;
}
private static T nonNull(T o, String message) {
if (o == null) {
throw new NullPointerException(message);
}
return o;
}
/**
* Gets type from super class's type parameter.
*/
static Type getSuperclassTypeParameter(Class> subclass) {
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
return ((ParameterizedType) superclass).getActualTypeArguments()[0];
}
/**
* Gets type token from super class's type parameter.
*/
static TypeToken> fromSuperclassTypeParameter(Class> subclass) {
return new SimpleTypeToken