public Map<TypeVariable<?>, Type> getGenericArgumentMap(Type... arguments) { if (arguments != null && representingClass.getTypeParameters().length != arguments.length && arguments.length != 0) { throw new IllegalArgumentException( "arguments length != " + representingClass.getTypeParameters().length); } GenericInfo<T> genericInfo = applyArguments0(arguments); return Collections.unmodifiableMap(genericInfo.genericArgumentMap); }
/** * A simplistic implementation, it may not handle all cases but it should handle enough. * * @param implementation the type for which the parameter requires a resolution * @param type the type that owns the parameter * @param parameterIndex the parameter index * @return the resolved type */ public static Type resolve(Type implementation, Class<?> type, int parameterIndex) { if (implementation == null) { throw new NullPointerException(); } // if (implementation == type) { TypeVariable<? extends Class<?>>[] tp = type.getTypeParameters(); if (parameterIndex < tp.length) { return tp[parameterIndex]; } else { throw new IllegalArgumentException(); } } else if (implementation instanceof Class<?>) { Class<?> c = (Class<?>) implementation; Type gsc = c.getGenericSuperclass(); Type resolved = null; if (gsc != null) { resolved = resolve(gsc, type, parameterIndex); if (resolved == null) { // Try with interface } } return resolved; } else if (implementation instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) implementation; Type[] typeArgs = pt.getActualTypeArguments(); Type rawType = pt.getRawType(); if (rawType == type) { return typeArgs[parameterIndex]; } else if (rawType instanceof Class<?>) { Class<?> classRawType = (Class<?>) rawType; Type resolved = resolve(classRawType, type, parameterIndex); if (resolved == null) { return null; } else if (resolved instanceof TypeVariable) { TypeVariable resolvedTV = (TypeVariable) resolved; TypeVariable[] a = classRawType.getTypeParameters(); for (int i = 0; i < a.length; i++) { if (a[i].equals(resolvedTV)) { return resolve(implementation, classRawType, i); } } throw new AssertionError(); } else { throw new UnsupportedOperationException("Cannot support resolution of " + resolved); } } else { throw new UnsupportedOperationException(); } } else { throw new UnsupportedOperationException( "todo " + implementation + " " + implementation.getClass()); } }
/** Checks for validity for classpath scanning. */ public static boolean isValid(Class<?> type) { if (type.isInterface()) return false; if (type.getTypeParameters() != null && type.getTypeParameters().length > 0) { return false; } if (!isValidConstructor(type)) return false; return true; }
/** Resolves <code>TypeVariable</code> with given implementation class. */ public static Type resolveVariable(TypeVariable variable, final Class implClass) { final Class rawType = getRawType(implClass, null); int index = ArraysUtil.indexOf(rawType.getTypeParameters(), variable); if (index >= 0) { return variable; } final Class[] interfaces = rawType.getInterfaces(); final Type[] genericInterfaces = rawType.getGenericInterfaces(); for (int i = 0; i <= interfaces.length; i++) { Class rawInterface; if (i < interfaces.length) { rawInterface = interfaces[i]; } else { rawInterface = rawType.getSuperclass(); if (rawInterface == null) { continue; } } final Type resolved = resolveVariable(variable, rawInterface); if (resolved instanceof Class || resolved instanceof ParameterizedType) { return resolved; } if (resolved instanceof TypeVariable) { final TypeVariable typeVariable = (TypeVariable) resolved; index = ArraysUtil.indexOf(rawInterface.getTypeParameters(), typeVariable); if (index < 0) { throw new IllegalArgumentException("Invalid type variable:" + typeVariable); } final Type type = i < genericInterfaces.length ? genericInterfaces[i] : rawType.getGenericSuperclass(); if (type instanceof Class) { return Object.class; } if (type instanceof ParameterizedType) { return ((ParameterizedType) type).getActualTypeArguments()[index]; } throw new IllegalArgumentException("Unsupported type: " + type); } } return null; }
private ReferenceTypeUsage toReferenceTypeUsage(Class<?> clazz, Type type) { TypeDefinition typeDefinition = new ReflectionBasedTypeDefinition(clazz); ReferenceTypeUsage referenceTypeUsage = new ReferenceTypeUsage(typeDefinition); if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; for (int tp = 0; tp < clazz.getTypeParameters().length; tp++) { TypeVariable<? extends Class<?>> typeVariable = clazz.getTypeParameters()[tp]; Type parameterType = parameterizedType.getActualTypeArguments()[tp]; referenceTypeUsage .getTypeParameterValues() .add(typeVariable.getName(), toTypeUsage(parameterType)); } } return referenceTypeUsage; }
/** * @param cls * @param toClass * @param subtypeVarAssigns * @return */ private static Map<TypeVariable<?>, Type> getTypeArguments( Class<?> cls, Class<?> toClass, Map<TypeVariable<?>, Type> subtypeVarAssigns) { // make sure they're assignable if (!isAssignable(cls, toClass)) { return null; } // can't work with primitives if (cls.isPrimitive()) { // both classes are primitives? if (toClass.isPrimitive()) { // dealing with widening here. No type arguments to be // harvested with these two types. return new HashMap<TypeVariable<?>, Type>(); } // work with wrapper the wrapper class instead of the primitive cls = ClassUtils.primitiveToWrapper(cls); } // create a copy of the incoming map, or an empty one if it's null HashMap<TypeVariable<?>, Type> typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>() : new HashMap<TypeVariable<?>, Type>(subtypeVarAssigns); // no arguments for the parameters, or target class has been reached if (cls.getTypeParameters().length > 0 || toClass.equals(cls)) { return typeVarAssigns; } // walk the inheritance hierarchy until the target class is reached return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns); }
private void readActualTypeParametersOnDeclaringClass() { registerTypeParametersOn(clazz.getTypeParameters()); registerTypeVariablesOn(clazz.getGenericSuperclass()); for (Type genericInterface : clazz.getGenericInterfaces()) { registerTypeVariablesOn(genericInterface); } }
public static boolean isParamerterizedTypeWithWildcard(Class<?> type) { if (isParameterizedType(type)) { return containsWildcards(type.getTypeParameters()); } else { return false; } }
private static Map getTypeArguments( ParameterizedType paramParameterizedType, Class paramClass, Map paramMap) { Class localClass = getRawType(paramParameterizedType); Object localObject; if (!isAssignable(localClass, paramClass)) localObject = null; do { return localObject; Type localType1 = paramParameterizedType.getOwnerType(); if ((localType1 instanceof ParameterizedType)) { ParameterizedType localParameterizedType = (ParameterizedType) localType1; localObject = getTypeArguments(localParameterizedType, getRawType(localParameterizedType), paramMap); } while (true) { Type[] arrayOfType = paramParameterizedType.getActualTypeArguments(); TypeVariable[] arrayOfTypeVariable = localClass.getTypeParameters(); for (int i = 0; i < arrayOfTypeVariable.length; i++) { Type localType2 = arrayOfType[i]; TypeVariable localTypeVariable = arrayOfTypeVariable[i]; if (((Map) localObject).containsKey(localType2)) localType2 = (Type) ((Map) localObject).get(localType2); ((Map) localObject).put(localTypeVariable, localType2); } if (paramMap == null) localObject = new HashMap(); else localObject = new HashMap(paramMap); } } while (paramClass.equals(localClass)); return getTypeArguments( getClosestParentType(localClass, paramClass), paramClass, (Map) localObject); }
private void doApplyArguments(Class<?> representingClass, Type[] actualArguments) { TypeVariable<?>[] declaredArguments = representingClass.getTypeParameters(); if (declaredArguments.length == 0) { // declaredArguments==0 assert (listenerMapping.size() == 0); // TODO ? // do nothing } else if (actualArguments == null || actualArguments.length == 0) { // actualArguments==0 List<TypeVariable<?>> toHandleArguments = new LinkedList<TypeVariable<?>>(); for (TypeVariable<?> declaredArgument : declaredArguments) { toHandleArguments.add(declaredArgument); } Map<TypeVariable<?>, Type> handledArguments = new HashMap<TypeVariable<?>, Type>(); while (toHandleArguments.size() > 0) { for (Iterator<TypeVariable<?>> iterator = toHandleArguments.iterator(); iterator.hasNext(); ) { TypeVariable<?> declaredArgument = iterator.next(); // Type defaultType = getDefaultType(declaredArgument.getBounds(), handledArguments, // declaredArgument); Type defaultType = getDefaultType(declaredArgument, handledArguments); if (defaultType != null) { // 没有保存==null的中间状态 iterator.remove(); handledArguments.put(declaredArgument, defaultType); changeGeneric(declaredArgument, defaultType); } } } } else { // actualArguments!=0 for (int i = 0; i < declaredArguments.length; i++) { Type actualArgument = actualArguments[i]; TypeVariable<?> declaredParameter = declaredArguments[i]; parseArgument(declaredParameter, actualArgument); } } }
private void buildGenericTypeVariables(Class<?>[] genericTypes) { if (samType.getTypeParameters().length != genericTypes.length) throw new LambdaException( "SAM class [%s] requires [%d] generic type variables, but only [%d] where provided", samType.getName(), samType.getTypeParameters().length, genericTypes.length); for (int i = 0; i < samType.getTypeParameters().length; i++) { TypeVariable typeVariable = samType.getTypeParameters()[i]; for (Type bound : typeVariable.getBounds()) if (bound instanceof Class<?> && !((Class) bound).isAssignableFrom(genericTypes[i])) throw new LambdaException( "SAM class [%s] generic type variable [%d, %s] is not compatible with generic parameter [%s]", samType.getName(), i, samType.getTypeParameters()[i].toString(), genericTypes[i]); materializedTypeVariableses.add( new MaterializedTypeVariable(typeVariable.getName(), genericTypes[i])); } }
ParameterizedTypeImpl(@Nullable Type var1, Class<?> var2, Type[] var3) { Preconditions.checkNotNull(var2); Preconditions.checkArgument(var3.length == var2.getTypeParameters().length); Types.disallowPrimitiveType(var3, "type parameter"); this.ownerType = var1; this.rawType = var2; this.argumentsList = Types.JavaVersion.CURRENT.usedInGenericType(var3); }
ParameterizedTypeImpl(@Nullable Type ownerType, Class<?> rawType, Type[] typeArguments) { checkNotNull(rawType); checkArgument(typeArguments.length == rawType.getTypeParameters().length); disallowPrimitiveType(typeArguments, "type parameter"); this.ownerType = ownerType; this.rawType = rawType; this.argumentsList = JavaVersion.CURRENT.usedInGenericType(typeArguments); }
public Map<TypeVariable<?>, Type> getVariableGenericArgumentMap() { Map<TypeVariable<?>, Type> genericArgumentMap = cloneGenericArgumentMap(); TypeVariable<?>[] declaredArguments = representingClass.getTypeParameters(); for (TypeVariable<?> var : declaredArguments) { genericArgumentMap.put(var, var); } return genericArgumentMap; }
private static ClassTypePair resolveTypeVariable( ParameterizedType pt, Class c, Class dc, TypeVariable tv, Map<TypeVariable, Type> map) { Type[] typeArguments = pt.getActualTypeArguments(); TypeVariable[] typeParameters = c.getTypeParameters(); Map<TypeVariable, Type> submap = new HashMap<TypeVariable, Type>(); for (int i = 0; i < typeArguments.length; i++) { // Substitute a type variable with the Java class if (typeArguments[i] instanceof TypeVariable) { Type t = map.get(typeArguments[i]); submap.put(typeParameters[i], t); } else { submap.put(typeParameters[i], typeArguments[i]); } } if (c == dc) { Type t = submap.get(tv); if (t instanceof Class) { return new ClassTypePair((Class) t); } else if (t instanceof GenericArrayType) { t = ((GenericArrayType) t).getGenericComponentType(); if (t instanceof Class) { c = (Class) t; try { return new ClassTypePair(getArrayClass(c)); } catch (Exception e) { } return null; } else if (t instanceof ParameterizedType) { Type rt = ((ParameterizedType) t).getRawType(); if (rt instanceof Class) { c = (Class) rt; } else { return null; } try { return new ClassTypePair(getArrayClass(c), t); } catch (Exception e) { return null; } } else { return null; } } else if (t instanceof ParameterizedType) { pt = (ParameterizedType) t; if (pt.getRawType() instanceof Class) { return new ClassTypePair((Class) pt.getRawType(), pt); } else return null; } else { return null; } } else { return resolveTypeVariable(c, dc, tv, submap); } }
public DiType(@NotNull Class<?> clazz, @NotNull List<DiType> typeParameters) { this.clazz = clazz; this.typeParameters = typeParameters; if (clazz.getTypeParameters().length != typeParameters.size()) { throw new IllegalStateException( "type parameter count mismatch: " + clazz + ", " + typeParameters); } }
private Class<?> findConcreteType( Type generic, Class<?> resource, Map<String, Type> parametersMap) throws ClassNotFoundException { for (Type superInterface : resource.getGenericInterfaces()) { if (superInterface instanceof ParameterizedType) { ParameterizedType p = (ParameterizedType) superInterface; Class<?> clazz = Class.forName( p.getRawType() .toString() .substring(p.getRawType().toString().lastIndexOf(' ') + 1)); Map<String, Type> map = new HashMap<>(); for (int i = 0; i < p.getActualTypeArguments().length; i++) { if (!map.containsKey(clazz.getTypeParameters()[i].toString())) { map.put(clazz.getTypeParameters()[i].toString(), p.getActualTypeArguments()[i]); } } if (map.containsKey(generic.toString())) { String type = map.get(generic.toString()).toString(); try { Class<?> returnClass = Class.forName(type.substring(type.lastIndexOf(' ') + 1)); return returnClass; } catch (ClassNotFoundException e) { break; } } } } if (parametersMap.containsKey(generic.toString())) { try { Type type = parametersMap.get(generic.toString()); Class<?> returnClass = Class.forName(type.toString().substring(type.toString().indexOf(' ') + 1)); return returnClass; } catch (ClassNotFoundException e) { return null; } } else { return null; } }
private void validateConstructorArguments() { TypeVariable /*<?>*/[] formals = rawType.getTypeParameters(); // check correct arity of actual type args if (formals.length != actualTypeArguments.length) { throw new MalformedParameterizedTypeException(); } /* for (int i = 0; i < actualTypeArguments.length; i++) { // check actuals against formals' bounds } */ }
@Override void visitParameterizedType(ParameterizedType parameterizedType) { Class<?> rawClass = (Class<?>) parameterizedType.getRawType(); TypeVariable<?>[] vars = rawClass.getTypeParameters(); Type[] typeArgs = parameterizedType.getActualTypeArguments(); checkState(vars.length == typeArgs.length); for (int i = 0; i < vars.length; i++) { map(vars[i], typeArgs[i]); } visit(rawClass); visit(parameterizedType.getOwnerType()); }
/** Private recursive helper function to actually do the type-safe checking of assignability. */ private static boolean isAssignableFrom( Type from, ParameterizedType to, Map<String, Type> typeVarMap) { if (from == null) { return false; } if (to.equals(from)) { return true; } // First figure out the class and any type information. Class<?> clazz = getRawType(from); ParameterizedType ptype = null; if (from instanceof ParameterizedType) { ptype = (ParameterizedType) from; } // Load up parameterized variable info if it was parameterized. if (ptype != null) { Type[] tArgs = ptype.getActualTypeArguments(); TypeVariable<?>[] tParams = clazz.getTypeParameters(); for (int i = 0; i < tArgs.length; i++) { Type arg = tArgs[i]; TypeVariable<?> var = tParams[i]; while (arg instanceof TypeVariable) { TypeVariable<?> v = (TypeVariable<?>) arg; arg = typeVarMap.get(v.getName()); } typeVarMap.put(var.getName(), arg); } // check if they are equivalent under our current mapping. if (typeEquals(ptype, to, typeVarMap)) { return true; } } for (Type itype : clazz.getGenericInterfaces()) { if (isAssignableFrom(itype, to, new HashMap<String, Type>(typeVarMap))) { return true; } } // Interfaces didn't work, try the superclass. Type sType = clazz.getGenericSuperclass(); if (isAssignableFrom(sType, to, new HashMap<String, Type>(typeVarMap))) { return true; } return false; }
/** * Returns the arguments of the provided generic class or interface. * * @param type the class to search. * @param args the class arguments. * @param clazz the generic class or interface of interest. * @return the arguments of the generic class or interface, or <code>null</code> if not found. */ protected static Type[] getTypeArguments(Class<?> type, Type[] args, Class<?> clazz) { if (type == clazz) { return args; } TypeVariable[] params = type.getTypeParameters(); for (Type iface : type.getGenericInterfaces()) { Type[] result = getTypeArguments(iface, params, args, clazz); if (result != null) { return result; } } return getTypeArguments(type.getGenericSuperclass(), params, args, clazz); }
/** * @param parameterizedType * @param toClass * @param subtypeVarAssigns * @return */ private static Map<TypeVariable<?>, Type> getTypeArguments( ParameterizedType parameterizedType, Class<?> toClass, Map<TypeVariable<?>, Type> subtypeVarAssigns) { Class<?> cls = getRawType(parameterizedType); // make sure they're assignable if (!isAssignable(cls, toClass)) { return null; } Type ownerType = parameterizedType.getOwnerType(); Map<TypeVariable<?>, Type> typeVarAssigns; if (ownerType instanceof ParameterizedType) { // get the owner type arguments first ParameterizedType parameterizedOwnerType = (ParameterizedType) ownerType; typeVarAssigns = getTypeArguments( parameterizedOwnerType, getRawType(parameterizedOwnerType), subtypeVarAssigns); } else { // no owner, prep the type variable assignments map typeVarAssigns = subtypeVarAssigns == null ? new HashMap<TypeVariable<?>, Type>() : new HashMap<TypeVariable<?>, Type>(subtypeVarAssigns); } // get the subject parameterized type's arguments Type[] typeArgs = parameterizedType.getActualTypeArguments(); // and get the corresponding type variables from the raw class TypeVariable<?>[] typeParams = cls.getTypeParameters(); // map the arguments to their respective type variables for (int i = 0; i < typeParams.length; i++) { Type typeArg = typeArgs[i]; typeVarAssigns.put( typeParams[i], typeVarAssigns.containsKey(typeArg) ? typeVarAssigns.get(typeArg) : typeArg); } if (toClass.equals(cls)) { // target class has been reached. Done. return typeVarAssigns; } // walk the inheritance hierarchy until the target class is reached return getTypeArguments(getClosestParentType(cls, toClass), toClass, typeVarAssigns); }
public static void main(String... args) { try { Class<?> c = Class.forName(args[0]); out.format("Class:%n %s%n%n", c.getCanonicalName()); out.format("Modifiers:%n %s%n%n", Modifier.toString(c.getModifiers())); out.format("Type Parameters:%n"); TypeVariable<?>[] tv = c.getTypeParameters(); if (tv.length != 0) { out.format(" "); for (TypeVariable<?> t : tv) out.format("%s ", t.getName()); out.format("%n%n"); } else { out.format(" -- No Type Parameters --%n%n"); } out.format("Implemented Interfaces:%n"); Type[] intfs = c.getGenericInterfaces(); if (intfs.length != 0) { for (Type intf : intfs) out.format(" %s%n", intf.toString()); out.format("%n"); } else { out.format(" -- No Implemented Interfaces --%n%n"); } out.format("Inheritance Path:%n"); List<Class<?>> l = new ArrayList<Class<?>>(); printAncestor(c, l); if (l.size() != 0) { for (Class<?> cl : l) out.format(" %s%n", cl.getCanonicalName()); out.format("%n"); } else { out.format(" -- No Super Classes --%n%n"); } out.format("Annotations:%n"); Annotation[] ann = c.getAnnotations(); if (ann.length != 0) { for (Annotation a : ann) out.format(" %s%n", a.toString()); out.format("%n"); } else { out.format(" -- No Annotations --%n%n"); } // production code should handle this exception more gracefully } catch (ClassNotFoundException x) { x.printStackTrace(); } }
private static void mapTypeVariablesToArguments( Class paramClass, ParameterizedType paramParameterizedType, Map paramMap) { Type localType1 = paramParameterizedType.getOwnerType(); if ((localType1 instanceof ParameterizedType)) mapTypeVariablesToArguments(paramClass, (ParameterizedType) localType1, paramMap); Type[] arrayOfType = paramParameterizedType.getActualTypeArguments(); TypeVariable[] arrayOfTypeVariable = getRawType(paramParameterizedType).getTypeParameters(); List localList = Arrays.asList(paramClass.getTypeParameters()); for (int i = 0; i < arrayOfType.length; i++) { TypeVariable localTypeVariable = arrayOfTypeVariable[i]; Type localType2 = arrayOfType[i]; if ((localList.contains(localType2)) && (paramMap.containsKey(localTypeVariable))) paramMap.put((TypeVariable) localType2, paramMap.get(localTypeVariable)); } }
/** * @param parameters the parameters of a direct superclass or interface * @param childClass an extending class * @param childParameters the actual parameters of the extending class * @return the actual parameters of the direct superclass or interface, return null if it's * impossible to resolve */ public static Type[] resolveSuperArguments( Type[] parameters, Class childClass, Type[] childParameters) { Map<TypeVariable, Type> typeMapping; if (childParameters != null) { TypeVariable<Class>[] declaredChildParameters = childClass.getTypeParameters(); typeMapping = new HashMap<TypeVariable, Type>(); for (int i = 0; i < declaredChildParameters.length; ++i) { typeMapping.put(declaredChildParameters[i], childParameters[i]); } } else { typeMapping = Collections.emptyMap(); } return resolveTypes(parameters, typeMapping); }
static Type resolveTypeVariable(Type context, Class<?> contextRawType, TypeVariable<?> unknown) { Class<?> declaredByRaw = declaringClassOf(unknown); // we can't reduce this further if (declaredByRaw == null) { return unknown; } Type declaredBy = getGenericSupertype(context, contextRawType, declaredByRaw); if (declaredBy instanceof ParameterizedType) { int index = indexOf(declaredByRaw.getTypeParameters(), unknown); return ((ParameterizedType) declaredBy).getActualTypeArguments()[index]; } return unknown; }
/** Return a {@link Serializable} variant of {@link Class#getTypeParameters()}. */ @SuppressWarnings("serial") public static Type[] forTypeParameters(final Class<?> type) { Type[] result = new Type[type.getTypeParameters().length]; for (int i = 0; i < result.length; i++) { final int index = i; result[i] = forTypeProvider( new DefaultTypeProvider() { @Override public Type getType() { return type.getTypeParameters()[index]; } }); } return result; }
private static Map getTypeArguments(Class paramClass1, Class paramClass2, Map paramMap) { Object localObject; if (!isAssignable(paramClass1, paramClass2)) localObject = null; while (true) { return localObject; if (paramClass1.isPrimitive()) { if (paramClass2.isPrimitive()) return new HashMap(); paramClass1 = ClassUtils.primitiveToWrapper(paramClass1); } if (paramMap == null) ; for (localObject = new HashMap(); (paramClass1.getTypeParameters().length <= 0) && (!paramClass2.equals(paramClass1)); localObject = new HashMap(paramMap)) return getTypeArguments( getClosestParentType(paramClass1, paramClass2), paramClass2, (Map) localObject); } }
protected static SimpleType _constructSimple(Class<?> rawType, JavaType[] parameterTypes) { // Quick sanity check: must match numbers of types with expected... TypeVariable<?>[] typeVars = rawType.getTypeParameters(); if (typeVars.length != parameterTypes.length) { throw new IllegalArgumentException( "Parameter type mismatch for " + rawType.getName() + ": expected " + typeVars.length + " parameters, was given " + parameterTypes.length); } String[] names = new String[typeVars.length]; for (int i = 0, len = typeVars.length; i < len; ++i) { names[i] = typeVars[i].getName(); } return new SimpleType(rawType, names, parameterTypes); }
/** Build a string representation of a type and optionally its generic type arguments. */ public static String type(Class<?> raw, String... parameters) { if (parameters.length == 0) { return raw.getCanonicalName(); } if (raw.getTypeParameters().length != parameters.length) { throw new IllegalArgumentException(); } StringBuilder result = new StringBuilder(); result.append(raw.getCanonicalName()); result.append("<"); result.append(parameters[0]); for (int i = 1; i < parameters.length; i++) { result.append(", "); result.append(parameters[i]); } result.append(">"); return result.toString(); }