1 16 17 package com.google.inject; 18 19 import static com.google.inject.util.Objects.nonNull; 20 import java.lang.reflect.ParameterizedType ; 21 import java.lang.reflect.Type ; 22 import java.lang.reflect.GenericArrayType ; 23 import java.lang.reflect.Array ; 24 import java.util.Arrays ; 25 26 43 public abstract class TypeLiteral<T> { 44 45 final Class <? super T> rawType; 46 final Type type; 47 final int hashCode; 48 49 57 @SuppressWarnings ("unchecked") 58 protected TypeLiteral() { 59 this.type = getSuperclassTypeParameter(getClass()); 60 this.rawType = (Class <? super T>) getRawType(type); 61 this.hashCode = hashCode(type); 62 } 63 64 67 @SuppressWarnings ("unchecked") 68 TypeLiteral(Type type) { 69 this.rawType = (Class <? super T>) getRawType(nonNull(type, "type")); 70 this.type = type; 71 this.hashCode = hashCode(type); 72 } 73 74 77 static Type getSuperclassTypeParameter(Class <?> subclass) { 78 Type superclass = subclass.getGenericSuperclass(); 79 if (superclass instanceof Class ) { 80 throw new RuntimeException ("Missing type parameter."); 81 } 82 return ((ParameterizedType ) superclass).getActualTypeArguments()[0]; 83 } 84 85 88 static TypeLiteral<?> fromSuperclassTypeParameter(Class <?> subclass) { 89 return new SimpleTypeLiteral<Object >(getSuperclassTypeParameter(subclass)); 90 } 91 92 @SuppressWarnings ({ "unchecked" }) 93 private static Class <?> getRawType(Type type) { 94 if (type instanceof Class <?>) { 95 return (Class <?>) type; 97 } 98 else { 99 if (type instanceof ParameterizedType ) { 100 ParameterizedType parameterizedType = (ParameterizedType ) type; 101 102 Type rawType = parameterizedType.getRawType(); 106 if (!(rawType instanceof Class <?>)) { 107 throw unexpectedType(rawType, Class .class); 108 } 109 return (Class <?>) rawType; 110 } 111 112 if (type instanceof GenericArrayType ) { 113 return Object [].class; 115 } 116 117 throw unexpectedType(type, ParameterizedType .class); 119 } 120 } 121 122 125 Class <? super T> getRawType() { 126 return rawType; 127 } 128 129 132 public Type getType() { 133 return type; 134 } 135 136 public int hashCode() { 137 return this.hashCode; 138 } 139 140 public boolean equals(Object o) { 141 if (o == this) { 142 return true; 143 } 144 if (!(o instanceof TypeLiteral<?>)) { 145 return false; 146 } 147 TypeLiteral<?> other = (TypeLiteral<?>) o; 148 149 return equals(type, other.type); 150 } 151 152 public String toString() { 153 return type instanceof Class <?> 154 ? ((Class <?>) type).getName() 155 : type.toString(); 156 } 157 158 static AssertionError unexpectedType(Type type, Class <?> expected) { 159 return new AssertionError ( 160 "Unexpected type. Expected: " + expected.getName() 161 + ", got: " + type.getClass().getName() 162 + ", for type literal: " + type.toString() + "."); 163 } 164 165 168 public static TypeLiteral<?> get(Type type) { 169 return new SimpleTypeLiteral<Object >(type); 170 } 171 172 175 public static <T> TypeLiteral<T> get(Class <T> type) { 176 return new SimpleTypeLiteral<T>(type); 177 } 178 179 private static class SimpleTypeLiteral<T> extends TypeLiteral<T> { 180 public SimpleTypeLiteral(Type type) { 181 super(type); 182 } 183 } 184 185 static int hashCode(Type type) { 186 if (type instanceof ParameterizedType ) { 187 ParameterizedType p = (ParameterizedType ) type; 188 int h = p.getRawType().hashCode(); 189 for (Type argument : p.getActualTypeArguments()) { 190 h = h * 31 + hashCode(argument); 191 } 192 return h; 193 } 194 195 if (type instanceof Class ) { 196 return type.hashCode(); 198 } 199 200 if (type instanceof GenericArrayType ) { 201 return hashCode(((GenericArrayType ) type).getGenericComponentType()) * 31; 202 } 203 204 return type.hashCode(); 207 } 208 209 static boolean equals(Type a, Type b) { 210 if (a instanceof Class ) { 211 return a.equals(b); 213 } 214 215 if (a instanceof ParameterizedType ) { 216 if (!(b instanceof ParameterizedType )) { 217 return false; 218 } 219 220 ParameterizedType pa = (ParameterizedType ) a; 221 ParameterizedType pb = (ParameterizedType ) b; 222 223 if (!pa.getRawType().equals(pb.getRawType())) { 224 return false; 225 } 226 227 Type [] aa = pa.getActualTypeArguments(); 228 Type [] ba = pb.getActualTypeArguments(); 229 if (aa.length != ba.length) { 230 return false; 231 } 232 233 for (int i = 0; i < aa.length; i++) { 234 if (!equals(aa[i], ba[i])) { 235 return false; 236 } 237 } 238 239 return true; 240 } 241 242 if (a instanceof GenericArrayType ) { 243 if (!(b instanceof GenericArrayType )) { 244 return false; 245 } 246 247 return equals( 248 ((GenericArrayType ) a).getGenericComponentType(), 249 ((GenericArrayType ) b).getGenericComponentType() 250 ); 251 } 252 253 return false; 256 } 257 } 258 | Popular Tags |