|
Java example source code file (TypeToken.java)
This example Java source code file (TypeToken.java) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Learn more about this Java project at its project page.
The TypeToken.java Java example source code
/*
* Copyright (C) 2006 The Guava Authors
*
* 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.common.reflect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Primitives;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
/**
* A {@link Type} with generics.
*
* <p>Operations that are otherwise only available in {@link Class} are implemented to support
* {@code Type}, for example {@link #isSubtypeOf}, {@link #isArray} and {@link #getComponentType}.
* It also provides additional utilities such as {@link #getTypes}, {@link #resolveType}, etc.
*
* <p>There are three ways to get a {@code TypeToken} instance:
*
* <ul>
*
* <li>Wrap a {@code Type} obtained via reflection. For example:
* {@code TypeToken.of(method.getGenericReturnType())}.
*
* <li>Capture a generic type with a (usually anonymous) subclass. For example: {@code
* new TypeToken<List() {}}
*
* <p>Note that it's critical that the actual type argument is carried by a subclass. The
* following code is wrong because it only captures the {@code <T>} type variable of the {@code
* listType()} method signature; while {@code <String>} is lost in erasure:
*
* <pre> {@code
* class Util {
* static <T> TypeToken> listType() {
* return new TypeToken<List() {};
* }
* }
*
* TypeToken<List stringListType = Util.listType();}
*
* <li>Capture a generic type with a (usually anonymous) subclass and resolve it against a context
* class that knows what the type parameters are. For example: <pre> {@code
* abstract class IKnowMyType<T> {
* TypeToken<T> type = new TypeToken (getClass()) {};
* }
* new IKnowMyType<String>() {}.type => String}
*
* </ul>
*
* <p>{@code TypeToken} is serializable when no type variable is contained in the type.
*
* <p>Note to Guice users: {@code} TypeToken is similar to Guice's {@code TypeLiteral} class except
* that it is serializable and offers numerous additional utility methods.
*
* @author Bob Lee
* @author Sven Mawson
* @author Ben Yu
* @since 12.0
*/
@Beta
@SuppressWarnings("serial") // SimpleTypeToken is the serialized form.
public abstract class TypeToken<T> extends TypeCapture implements Serializable {
private final Type runtimeType;
/** Resolver for resolving types with {@link #runtimeType} as context. */
private transient TypeResolver typeResolver;
/**
* Constructs a new type token of {@code T}.
*
* <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.
*
* <p>For example: {@code
* TypeToken<List t = new TypeToken>() {};}
*/
protected TypeToken() {
this.runtimeType = capture();
checkState(
!(runtimeType instanceof TypeVariable),
"Cannot construct a TypeToken for a type variable.\n"
+ "You probably meant to call new TypeToken<%s>(getClass()) "
+ "that can resolve the type variable for you.\n"
+ "If you do need to create a TypeToken of a type variable, "
+ "please use TypeToken.of() instead.",
runtimeType);
}
/**
* Constructs a new type token of {@code T} while resolving free type variables in the context of
* {@code declaringClass}.
*
* <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.
*
* <p>For example: {@code
* abstract class IKnowMyType<T> {
* TypeToken<T> getMyType() {
* return new TypeToken<T>(getClass()) {};
* }
* }
*
* new IKnowMyType<String>() {}.getMyType() => String}
*/
protected TypeToken(Class<?> declaringClass) {
Type captured = super.capture();
if (captured instanceof Class) {
this.runtimeType = captured;
} else {
this.runtimeType = of(declaringClass).resolveType(captured).runtimeType;
}
}
private TypeToken(Type type) {
this.runtimeType = checkNotNull(type);
}
/** Returns an instance of type token that wraps {@code type}. */
public static <T> TypeToken of(Class type) {
return new SimpleTypeToken<T>(type);
}
/** Returns an instance of type token that wraps {@code type}. */
public static TypeToken<?> of(Type type) {
return new SimpleTypeToken<Object>(type);
}
/**
* Returns the raw type of {@code T}. Formally speaking, if {@code T} is returned by
* {@link java.lang.reflect.Method#getGenericReturnType}, the raw type is what's returned by
* {@link java.lang.reflect.Method#getReturnType} of the same method object. Specifically:
* <ul>
* <li>If {@code T} is a {@code Class} itself, {@code T} itself is returned.
* <li>If {@code T} is a {@link ParameterizedType}, the raw type of the parameterized type is
* returned.
* <li>If {@code T} is a {@link GenericArrayType}, the returned type is the corresponding array
* class. For example: {@code List<Integer>[] => List[]}.
* <li>If {@code T} is a type variable or a wildcard type, the raw type of the first upper bound
* is returned. For example: {@code <X extends Foo> => Foo}.
* </ul>
*/
public final Class<? super T> getRawType() {
// For wildcard or type variable, the first bound determines the runtime type.
Class<?> rawType = getRawTypes().iterator().next();
@SuppressWarnings("unchecked") // raw type is |T|
Class<? super T> result = (Class) rawType;
return result;
}
/** Returns the represented type. */
public final Type getType() {
return runtimeType;
}
/**
* <p>Returns a new {@code TypeToken} where type variables represented by {@code typeParam} are
* substituted by {@code typeArg}. For example, it can be used to construct {@code Map<K, V>} for
* any {@code K} and {@code V} type: <pre> {@code
* static <K, V> TypeToken |