TypeLiteral.java revision 0baa9fcb9ddf853e9bbf8b71c5f1167051c366e0
141bc85288590d19c50f299372f942aa27677d77ccrazyboblee/** 241bc85288590d19c50f299372f942aa27677d77ccrazyboblee * Copyright (C) 2006 Google Inc. 341bc85288590d19c50f299372f942aa27677d77ccrazyboblee * 441bc85288590d19c50f299372f942aa27677d77ccrazyboblee * Licensed under the Apache License, Version 2.0 (the "License"); 541bc85288590d19c50f299372f942aa27677d77ccrazyboblee * you may not use this file except in compliance with the License. 641bc85288590d19c50f299372f942aa27677d77ccrazyboblee * You may obtain a copy of the License at 741bc85288590d19c50f299372f942aa27677d77ccrazyboblee * 841bc85288590d19c50f299372f942aa27677d77ccrazyboblee * http://www.apache.org/licenses/LICENSE-2.0 941bc85288590d19c50f299372f942aa27677d77ccrazyboblee * 1041bc85288590d19c50f299372f942aa27677d77ccrazyboblee * Unless required by applicable law or agreed to in writing, software 1141bc85288590d19c50f299372f942aa27677d77ccrazyboblee * distributed under the License is distributed on an "AS IS" BASIS, 1241bc85288590d19c50f299372f942aa27677d77ccrazyboblee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1341bc85288590d19c50f299372f942aa27677d77ccrazyboblee * See the License for the specific language governing permissions and 1441bc85288590d19c50f299372f942aa27677d77ccrazyboblee * limitations under the License. 1541bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 1641bc85288590d19c50f299372f942aa27677d77ccrazyboblee 1741bc85288590d19c50f299372f942aa27677d77ccrazybobleepackage com.google.inject; 1841bc85288590d19c50f299372f942aa27677d77ccrazyboblee 1941bc85288590d19c50f299372f942aa27677d77ccrazybobleeimport static com.google.inject.util.Objects.nonNull; 2041bc85288590d19c50f299372f942aa27677d77ccrazyboblee 2141bc85288590d19c50f299372f942aa27677d77ccrazybobleeimport java.lang.reflect.Type; 2241bc85288590d19c50f299372f942aa27677d77ccrazybobleeimport java.lang.reflect.ParameterizedType; 2341bc85288590d19c50f299372f942aa27677d77ccrazyboblee 2441bc85288590d19c50f299372f942aa27677d77ccrazyboblee/** 25235d068516b98fcbf9c6f1a05bcbd9d3e97a71d5crazyboblee * Represents a generic type {@code T}. Java doesn't yet provide a way to 26235d068516b98fcbf9c6f1a05bcbd9d3e97a71d5crazyboblee * represent generic types, so this class does. 2741bc85288590d19c50f299372f942aa27677d77ccrazyboblee * 2841bc85288590d19c50f299372f942aa27677d77ccrazyboblee * <p>Assumes {@code Type} implements {@code equals()} and {@code hashCode()} 2941bc85288590d19c50f299372f942aa27677d77ccrazyboblee * as a value (as opposed to identity) comparison. 3041bc85288590d19c50f299372f942aa27677d77ccrazyboblee * 3141bc85288590d19c50f299372f942aa27677d77ccrazyboblee * @author crazybob@google.com (Bob Lee) 3241bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 330baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazybobleepublic abstract class TypeLiteral<T> { 3441bc85288590d19c50f299372f942aa27677d77ccrazyboblee 3541bc85288590d19c50f299372f942aa27677d77ccrazyboblee final Class<? super T> rawType; 3641bc85288590d19c50f299372f942aa27677d77ccrazyboblee final Type type; 3741bc85288590d19c50f299372f942aa27677d77ccrazyboblee 3841bc85288590d19c50f299372f942aa27677d77ccrazyboblee /** 390baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee * Constructs a new type literal. Derives represented class from type 4041bc85288590d19c50f299372f942aa27677d77ccrazyboblee * parameter. 4141bc85288590d19c50f299372f942aa27677d77ccrazyboblee * 4241bc85288590d19c50f299372f942aa27677d77ccrazyboblee * <p>Clients create an empty anonymous subclass. Doing so embeds the type 4341bc85288590d19c50f299372f942aa27677d77ccrazyboblee * parameter in the anonymous class's type hierarchy so we can reconstitute 4441bc85288590d19c50f299372f942aa27677d77ccrazyboblee * it at runtime despite erasure. 4541bc85288590d19c50f299372f942aa27677d77ccrazyboblee * 460baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee * <p>For example: {@code TypeLiteral<List<String>> t = new 470baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee * TypeLiteral<List<String>>() {};} 4841bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 4941bc85288590d19c50f299372f942aa27677d77ccrazyboblee @SuppressWarnings({"unchecked"}) 500baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee protected TypeLiteral() { 5141bc85288590d19c50f299372f942aa27677d77ccrazyboblee this.type = getSuperclassTypeParameter(getClass()); 5241bc85288590d19c50f299372f942aa27677d77ccrazyboblee this.rawType = (Class<? super T>) getRawType(type); 5341bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 5441bc85288590d19c50f299372f942aa27677d77ccrazyboblee 5541bc85288590d19c50f299372f942aa27677d77ccrazyboblee /** 560baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee * Unsafe. Constructs a type literal manually. 5741bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 5841bc85288590d19c50f299372f942aa27677d77ccrazyboblee @SuppressWarnings({"unchecked"}) 590baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee private TypeLiteral(Type type) { 6041bc85288590d19c50f299372f942aa27677d77ccrazyboblee this.rawType = (Class<? super T>) getRawType(nonNull(type, "type")); 6141bc85288590d19c50f299372f942aa27677d77ccrazyboblee this.type = type; 6241bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 6341bc85288590d19c50f299372f942aa27677d77ccrazyboblee 6441bc85288590d19c50f299372f942aa27677d77ccrazyboblee /** 6541bc85288590d19c50f299372f942aa27677d77ccrazyboblee * Gets type from super class's type parameter. 6641bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 6741bc85288590d19c50f299372f942aa27677d77ccrazyboblee static Type getSuperclassTypeParameter(Class<?> subclass) { 6841bc85288590d19c50f299372f942aa27677d77ccrazyboblee Type superclass = subclass.getGenericSuperclass(); 6941bc85288590d19c50f299372f942aa27677d77ccrazyboblee if (superclass instanceof Class) { 7041bc85288590d19c50f299372f942aa27677d77ccrazyboblee throw new RuntimeException("Missing type parameter."); 7141bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 7241bc85288590d19c50f299372f942aa27677d77ccrazyboblee return ((ParameterizedType) superclass).getActualTypeArguments()[0]; 7341bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 7441bc85288590d19c50f299372f942aa27677d77ccrazyboblee 7541bc85288590d19c50f299372f942aa27677d77ccrazyboblee /** 760baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee * Gets type literal from super class's type parameter. 7741bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 780baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee static TypeLiteral<?> fromSuperclassTypeParameter(Class<?> subclass) { 790baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee return new SimpleTypeLiteral<Object>(getSuperclassTypeParameter(subclass)); 8041bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 8141bc85288590d19c50f299372f942aa27677d77ccrazyboblee 8241bc85288590d19c50f299372f942aa27677d77ccrazyboblee @SuppressWarnings({"unchecked"}) 8341bc85288590d19c50f299372f942aa27677d77ccrazyboblee private static Class<?> getRawType(Type type) { 8441bc85288590d19c50f299372f942aa27677d77ccrazyboblee if (type instanceof Class<?>) { 8541bc85288590d19c50f299372f942aa27677d77ccrazyboblee // type is a normal class. 8641bc85288590d19c50f299372f942aa27677d77ccrazyboblee return (Class<?>) type; 8741bc85288590d19c50f299372f942aa27677d77ccrazyboblee } else { 8841bc85288590d19c50f299372f942aa27677d77ccrazyboblee // type is a parameterized type. 8941bc85288590d19c50f299372f942aa27677d77ccrazyboblee if (!(type instanceof ParameterizedType)) { 9041bc85288590d19c50f299372f942aa27677d77ccrazyboblee unexpectedType(type, ParameterizedType.class); 9141bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 9241bc85288590d19c50f299372f942aa27677d77ccrazyboblee ParameterizedType parameterizedType = (ParameterizedType) type; 9341bc85288590d19c50f299372f942aa27677d77ccrazyboblee 9441bc85288590d19c50f299372f942aa27677d77ccrazyboblee // I'm not exactly sure why getRawType() returns Type instead of Class. 9541bc85288590d19c50f299372f942aa27677d77ccrazyboblee // Neal isn't either but suspects some pathological case related 9641bc85288590d19c50f299372f942aa27677d77ccrazyboblee // to nested classes exists. 9741bc85288590d19c50f299372f942aa27677d77ccrazyboblee Type rawType = parameterizedType.getRawType(); 9841bc85288590d19c50f299372f942aa27677d77ccrazyboblee if (!(rawType instanceof Class<?>)) { 9941bc85288590d19c50f299372f942aa27677d77ccrazyboblee unexpectedType(rawType, Class.class); 10041bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 10141bc85288590d19c50f299372f942aa27677d77ccrazyboblee return (Class<?>) rawType; 10241bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 10341bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 10441bc85288590d19c50f299372f942aa27677d77ccrazyboblee 10541bc85288590d19c50f299372f942aa27677d77ccrazyboblee /** 10641bc85288590d19c50f299372f942aa27677d77ccrazyboblee * Gets the raw type. 10741bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 10841bc85288590d19c50f299372f942aa27677d77ccrazyboblee Class<? super T> getRawType() { 10941bc85288590d19c50f299372f942aa27677d77ccrazyboblee return rawType; 11041bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 11141bc85288590d19c50f299372f942aa27677d77ccrazyboblee 11241bc85288590d19c50f299372f942aa27677d77ccrazyboblee /** 11341bc85288590d19c50f299372f942aa27677d77ccrazyboblee * Gets underlying {@code Type} instance. 11441bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 11541bc85288590d19c50f299372f942aa27677d77ccrazyboblee public Type getType() { 11641bc85288590d19c50f299372f942aa27677d77ccrazyboblee return type; 11741bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 11841bc85288590d19c50f299372f942aa27677d77ccrazyboblee 11941bc85288590d19c50f299372f942aa27677d77ccrazyboblee public int hashCode() { 12041bc85288590d19c50f299372f942aa27677d77ccrazyboblee return type.hashCode(); 12141bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 12241bc85288590d19c50f299372f942aa27677d77ccrazyboblee 12341bc85288590d19c50f299372f942aa27677d77ccrazyboblee public boolean equals(Object o) { 12441bc85288590d19c50f299372f942aa27677d77ccrazyboblee if (o == this) { 12541bc85288590d19c50f299372f942aa27677d77ccrazyboblee return true; 12641bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 1270baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee if (!(o instanceof TypeLiteral<?>)) { 12841bc85288590d19c50f299372f942aa27677d77ccrazyboblee return false; 12941bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 1300baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee TypeLiteral<?> t = (TypeLiteral<?>) o; 13141bc85288590d19c50f299372f942aa27677d77ccrazyboblee return type.equals(t.type); 13241bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 13341bc85288590d19c50f299372f942aa27677d77ccrazyboblee 13441bc85288590d19c50f299372f942aa27677d77ccrazyboblee public String toString() { 13541bc85288590d19c50f299372f942aa27677d77ccrazyboblee return type instanceof Class<?> 13641bc85288590d19c50f299372f942aa27677d77ccrazyboblee ? ((Class<?>) type).getName() 13741bc85288590d19c50f299372f942aa27677d77ccrazyboblee : type.toString(); 13841bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 13941bc85288590d19c50f299372f942aa27677d77ccrazyboblee 1400baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee static void unexpectedType(Type type, Class<?> expected) { 14141bc85288590d19c50f299372f942aa27677d77ccrazyboblee throw new AssertionError( 14241bc85288590d19c50f299372f942aa27677d77ccrazyboblee "Unexpected type. Expected: " + expected.getName() 1430baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee + ", got: " + type.getClass().getName() 1440baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee + ", for type literal: " + type.toString() + "."); 14541bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 14641bc85288590d19c50f299372f942aa27677d77ccrazyboblee 14741bc85288590d19c50f299372f942aa27677d77ccrazyboblee /** 1480baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee * Gets type literal for the given {@code Type} instance. 14941bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 1500baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee public static TypeLiteral<?> get(Type type) { 1510baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee return new SimpleTypeLiteral<Object>(type); 15241bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 15341bc85288590d19c50f299372f942aa27677d77ccrazyboblee 15441bc85288590d19c50f299372f942aa27677d77ccrazyboblee /** 1550baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee * Gets type literal for the given {@code Class} instance. 15641bc85288590d19c50f299372f942aa27677d77ccrazyboblee */ 1570baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee public static <T> TypeLiteral<T> get(Class<T> type) { 1580baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee return new SimpleTypeLiteral<T>(type); 15941bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 16041bc85288590d19c50f299372f942aa27677d77ccrazyboblee 1610baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee private static class SimpleTypeLiteral<T> extends TypeLiteral<T> { 1620baa9fcb9ddf853e9bbf8b71c5f1167051c366e0crazyboblee public SimpleTypeLiteral(Type type) { 16341bc85288590d19c50f299372f942aa27677d77ccrazyboblee super(type); 16441bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 16541bc85288590d19c50f299372f942aa27677d77ccrazyboblee } 16641bc85288590d19c50f299372f942aa27677d77ccrazyboblee} 167