下面列出了java.lang.reflect.MalformedParameterizedTypeException#java.lang.reflect.TypeVariable 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static Type resolveTypeVariable(Type type, TypeVariable t) {
TypeVariable<Class<Object>>[] typeParameters = TypeHelper.toClass(type).getTypeParameters();
for(int i = 0; i < typeParameters.length; i++) {
TypeVariable<Class<Object>> typeVariable = typeParameters[i];
if (typeVariable.getName().equals(t.getName())) {
if (type instanceof ParameterizedType) {
return ((ParameterizedType) type).getActualTypeArguments()[i];
} else {
return Object.class;
}
}
}
if (typeParameters.length == 1 && type instanceof ParameterizedType && ((ParameterizedType) type).getActualTypeArguments().length == 1) {
return ((ParameterizedType) type).getActualTypeArguments()[0];
}
return Object.class;
}
/** creates a map that maps generic type argument names to type tokens */
private static Map<String, TypeToken> getActualTypeArguments(TypeToken<?> typeToken) {
Class<?> rawClass = typeToken.getRawType();
Type type = typeToken.getType();
TypeVariable<? extends Class<?>>[] typeParameters = rawClass.getTypeParameters();
if (typeParameters==null || !(type instanceof ParameterizedType)) {
return null;
}
Map<String, TypeToken> genericTypes = new HashMap<>();
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (int i=0; i<typeParameters.length; i++) {
String typeParameterName = typeParameters[i].getName();
TypeToken<?> actualType = TypeToken.get(actualTypeArguments[i]);
genericTypes.put(typeParameterName, actualType);
}
return genericTypes;
}
/**
* Returns the generic form of {@code superclass}. For example, if this is
* {@code ArrayList<String>}, {@code Iterable<String>} is returned given the input
* {@code Iterable.class}.
*/
public final TypeToken<? super T> getSupertype(Class<? super T> superclass) {
checkArgument(this.someRawTypeIsSubclassOf(superclass), "%s is not a super class of %s", superclass, this);
if (runtimeType instanceof TypeVariable) {
return getSupertypeFromUpperBounds(superclass, ((TypeVariable<?>) runtimeType).getBounds());
}
if (runtimeType instanceof WildcardType) {
return getSupertypeFromUpperBounds(superclass, ((WildcardType) runtimeType).getUpperBounds());
}
if (superclass.isArray()) {
return getArraySupertype(superclass);
}
@SuppressWarnings("unchecked") // resolved supertype
TypeToken<? super T> supertype = (TypeToken<? super T>) resolveSupertype(toGenericType(superclass).runtimeType);
return supertype;
}
private ResolvableType resolveVariable(TypeVariable<?> variable) {
if (this.type instanceof TypeVariable) {
return resolveType().resolveVariable(variable);
}
if (this.type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) this.type;
TypeVariable<?>[] variables = resolve().getTypeParameters();
for (int i = 0; i < variables.length; i++) {
if (ObjectUtils.nullSafeEquals(variables[i].getName(), variable.getName())) {
Type actualType = parameterizedType.getActualTypeArguments()[i];
return forType(actualType, this.variableResolver);
}
}
if (parameterizedType.getOwnerType() != null) {
return forType(parameterizedType.getOwnerType(), this.variableResolver).resolveVariable(variable);
}
}
if (this.variableResolver != null) {
return this.variableResolver.resolveVariable(variable);
}
return null;
}
private static SpecimenTypeFields getFields(Type type, List<Type> recursiveGenericsGuard) {
if(type instanceof SpecimenType) return getSpecimenTypeFields((SpecimenType) type);
if(type instanceof Class) return getFieldsForClassType((Class)type, recursiveGenericsGuard);
if(type instanceof ParameterizedType) return getParameterizedTypeFields((ParameterizedType) type, recursiveGenericsGuard);
if(type instanceof GenericArrayType) return getGenericArrayFields((GenericArrayType) type);
if(type instanceof TypeVariable) {
// no type information for this type variable
SpecimenTypeFields fields = new SpecimenTypeFields();
fields.rawType = type.getClass();
fields.genericTypeArguments = GenericTypeCollection.empty();
return fields;
}
else if(type instanceof WildcardType)
throw new UnsupportedOperationException("Wildcard types not supported");
throw new UnsupportedOperationException(String.format("Unknown Type : %s", type.getClass()));
}
private Class<?> resolveClass(Type type, Class<?> subType) {
if (type instanceof Class) {
return (Class<?>) type;
} else if (type instanceof ParameterizedType) {
return resolveClass(((ParameterizedType) type).getRawType(), subType);
} else if (type instanceof GenericArrayType) {
GenericArrayType gat = (GenericArrayType) type;
Class<?> component = resolveClass(gat.getGenericComponentType(), subType);
return Array.newInstance(component, 0).getClass();
} else if (type instanceof TypeVariable<?>) {
TypeVariable<?> variable = (TypeVariable<?>) type;
Type resolvedType = getTypeVariableMap(subType).get(variable);
return (resolvedType == null) ? resolveClass(resolveBound(variable), subType)
: resolveClass(resolvedType, subType);
} else if (type instanceof WildcardType) {
WildcardType wcType = (WildcardType) type;
Type[] bounds = wcType.getLowerBounds().length == 0 ? wcType.getUpperBounds()
: wcType.getLowerBounds();
return resolveClass(bounds[0], subType);
}
// there are no more types in a standard JDK
throw new IllegalArgumentException("Unknown type: " + type);
}
private static String getInternalGenericName(Type genericType, int i) {
String genericName=null;
if (genericType instanceof ParameterizedType) { // 处理多级泛型
ParameterizedType subParameterizedType= (ParameterizedType) genericType;
genericName=subParameterizedType.getTypeName();
} else if (genericType instanceof GenericArrayType) { // 处理数组泛型
GenericArrayType genericArrayType= (GenericArrayType) genericType;
genericType = genericArrayType.getGenericComponentType();
//再递归一次
genericName =getInternalGenericName(genericType,i);
} else if (genericType instanceof TypeVariable) { // 处理泛型擦拭对象
TypeVariable<?> typeVariable =(TypeVariable<?>) genericType;
genericName =typeVariable.getName();
} else if (genericType instanceof WildcardType){
WildcardType wildcardType =((WildcardType)genericType);
genericName=wildcardType.getTypeName();
}
return genericName;
}
private static Type validateIsSupportedType(Type type) {
Validate.validState(type != null, "Type must not be null.");
Validate.validState(!(type instanceof GenericArrayType),
"Array type %s is not supported. Use java.util.List instead of arrays.", type);
Validate.validState(!(type instanceof TypeVariable), "Type variable type %s is not supported.", type);
if (type instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) type;
Validate.validState(wildcardType.getUpperBounds().length == 1 && wildcardType.getUpperBounds()[0] == Object.class,
"Non-Object wildcard type upper bounds are not supported.");
Validate.validState(wildcardType.getLowerBounds().length == 0,
"Wildcard type lower bounds are not supported.");
}
return type;
}
public static Class<?> getRawType(Type type) {
if (type instanceof Class) {
return (Class) type;
}
if (type instanceof ParameterizedType) {
Type rawType = ((ParameterizedType) type).getRawType();
C$Gson$Preconditions.checkArgument(rawType instanceof Class);
return (Class) rawType;
} else if (type instanceof GenericArrayType) {
return Array.newInstance(C$Gson$Types.getRawType(((GenericArrayType) type).getGenericComponentType()), 0).getClass();
} else {
if (type instanceof TypeVariable) {
return Object.class;
}
if (type instanceof WildcardType) {
return C$Gson$Types.getRawType(((WildcardType) type).getUpperBounds()[0]);
}
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or GenericArrayType, but <" + type + "> is of type " + (type == null ? "null" : type.getClass().getName()));
}
}
protected Map<String, Class<?>> prepareJsonBeanGenericMap(Type genericReturnType, Class<?> jsonBeanType) {
// can check: JsonResponse<LandBean<PiariBean>> landBean;
final Type[] resopnseArgTypes = DfReflectionUtil.getGenericParameterTypes(genericReturnType);
if (resopnseArgTypes.length > 0) { // just in case
final Type firstGenericType = resopnseArgTypes[0];
final Class<?> elementBeanType = DfReflectionUtil.getGenericFirstClass(firstGenericType);
if (elementBeanType != null && mayBeJsonBeanType(elementBeanType)) { // just in case
final Map<String, Class<?>> genericMap = new LinkedHashMap<String, Class<?>>(1); // only first generic #for_now
final TypeVariable<?>[] typeParameters = jsonBeanType.getTypeParameters();
if (typeParameters != null && typeParameters.length > 0) { // just in case
genericMap.put(typeParameters[0].getName(), elementBeanType); // e.g. DATA = PiariBean.class
return genericMap;
}
}
}
return Collections.emptyMap();
}
/**
* Learn, recursively, whether any of the type parameters associated with {@code type} are bound to variables.
*
* @param type the type to check for type variables
* @return boolean
* @since 3.2
*/
private static boolean containsTypeVariables(final Type type) {
if (type instanceof TypeVariable<?>) {
return true;
}
if (type instanceof Class<?>) {
return ((Class<?>) type).getTypeParameters().length > 0;
}
if (type instanceof ParameterizedType) {
for (final Type arg : ((ParameterizedType) type).getActualTypeArguments()) {
if (containsTypeVariables(arg)) {
return true;
}
}
return false;
}
if (type instanceof WildcardType) {
final WildcardType wild = (WildcardType) type;
return containsTypeVariables(TypeUtils.getImplicitLowerBounds(wild)[0])
|| containsTypeVariables(TypeUtils.getImplicitUpperBounds(wild)[0]);
}
return false;
}
/**
* Return the Type for the given java.lang.reflect.Type, either for a
* ParameterizedType or a Class instance
*
* @param type
*
* @return the resolved Type instance
*/
public static <T> Type<T> valueOf(final java.lang.reflect.Type type) {
if (type instanceof Type) {
return (Type<T>) type;
} else if (type instanceof ParameterizedType) {
return valueOf((ParameterizedType) type);
} else if (type instanceof Class) {
return valueOf((Class<T>) type);
} else if (type instanceof TypeVariable) {
return valueOf((TypeVariable<?>) type);
} else if (type instanceof WildcardType) {
return valueOf((WildcardType) type);
} else {
throw new IllegalArgumentException(type + " is an unsupported type");
}
}
private static Type[] extractTypeVariables(Map<String, Type> typeVarMap, Type[] types)
{
for (int j = 0; j < types.length; j++)
{
if (types[j] instanceof TypeVariable)
{
TypeVariable tv = (TypeVariable) types[j];
types[j] = typeVarMap.get(tv.getName());
}
else
{
types[j] = types[j];
}
}
return types;
}
@Test
@Deprecated
public void testCreateTypeVariableMap() throws Exception {
Map<TypeVariable, Type> typeVariableMap = GenericTypeResolver.getTypeVariableMap(MyBar.class);
TypeVariable<?> barT = findTypeVariable(InterBar.class, "T");
assertEquals(String.class, typeVariableMap.get(barT));
typeVariableMap = GenericTypeResolver.getTypeVariableMap(MyFoo.class);
TypeVariable<?> fooT = findTypeVariable(Foo.class, "T");
assertEquals(String.class, typeVariableMap.get(fooT));
typeVariableMap = GenericTypeResolver.getTypeVariableMap(ExtendsEnclosing.ExtendsEnclosed.ExtendsReallyDeepNow.class);
TypeVariable<?> r = findTypeVariable(Enclosing.Enclosed.ReallyDeepNow.class, "R");
TypeVariable<?> s = findTypeVariable(Enclosing.Enclosed.class, "S");
TypeVariable<?> t = findTypeVariable(Enclosing.class, "T");
assertEquals(Long.class, typeVariableMap.get(r));
assertEquals(Integer.class, typeVariableMap.get(s));
assertEquals(String.class, typeVariableMap.get(t));
}
private Class<?> extractRawTypeOf(Type type) {
if (type instanceof Class) {
return (Class<?>) type;
}
if (type instanceof ParameterizedType) {
return (Class<?>) ((ParameterizedType) type).getRawType();
}
if (type instanceof BoundedType) {
return extractRawTypeOf(((BoundedType) type).firstBound());
}
if (type instanceof TypeVariable) {
/*
* If type is a TypeVariable, then it is needed to gather data elsewhere. Usually TypeVariables are declared
* on the class definition, such as such as List<E>.
*/
return extractRawTypeOf(contextualActualTypeParameters.get(type));
}
throw new MockitoException("Raw extraction not supported for : '" + type + "'");
}
@Test
public void testGetTypeArguments() {
Map<TypeVariable<?>, Type> typeVarAssigns;
TypeVariable<?> treeSetTypeVar;
Type typeArg;
typeVarAssigns = TypeUtils.getTypeArguments(Integer.class, Comparable.class);
treeSetTypeVar = Comparable.class.getTypeParameters()[0];
Assert.assertTrue("Type var assigns for Comparable from Integer: " + typeVarAssigns,
typeVarAssigns.containsKey(treeSetTypeVar));
typeArg = typeVarAssigns.get(treeSetTypeVar);
Assert.assertEquals("Type argument of Comparable from Integer: " + typeArg, Integer.class,
typeVarAssigns.get(treeSetTypeVar));
typeVarAssigns = TypeUtils.getTypeArguments(int.class, Comparable.class);
treeSetTypeVar = Comparable.class.getTypeParameters()[0];
Assert.assertTrue("Type var assigns for Comparable from int: " + typeVarAssigns,
typeVarAssigns.containsKey(treeSetTypeVar));
typeArg = typeVarAssigns.get(treeSetTypeVar);
Assert.assertEquals("Type argument of Comparable from int: " + typeArg, Integer.class,
typeVarAssigns.get(treeSetTypeVar));
Collection<Integer> col = Arrays.asList(new Integer[0]);
typeVarAssigns = TypeUtils.getTypeArguments(List.class, Collection.class);
treeSetTypeVar = Comparable.class.getTypeParameters()[0];
Assert.assertFalse("Type var assigns for Collection from List: " + typeVarAssigns,
typeVarAssigns.containsKey(treeSetTypeVar));
typeVarAssigns = TypeUtils.getTypeArguments(AAAClass.BBBClass.class, AAClass.BBClass.class);
Assert.assertTrue(typeVarAssigns.size() == 2);
Assert.assertEquals(String.class, typeVarAssigns.get(AAClass.class.getTypeParameters()[0]));
Assert.assertEquals(String.class, typeVarAssigns.get(AAClass.BBClass.class.getTypeParameters()[0]));
typeVarAssigns = TypeUtils.getTypeArguments(Other.class, This.class);
Assert.assertEquals(2, typeVarAssigns.size());
Assert.assertEquals(String.class, typeVarAssigns.get(This.class.getTypeParameters()[0]));
Assert.assertEquals(Other.class.getTypeParameters()[0], typeVarAssigns.get(This.class.getTypeParameters()[1]));
}
public void testSimpleTypeVariableOnClass(){
Class<? extends A> clazz = A.class;
TypeVariable[] typeParameters = clazz.getTypeParameters();
assertLenghtOne(typeParameters);
TypeVariable<Class> typeVariable = typeParameters[0];
assertEquals(clazz, typeVariable.getGenericDeclaration());
assertEquals("T", typeVariable.getName());
assertEquals("T", typeVariable.toString());
assertEquals("T", typeVariable.getTypeName());
Type[] bounds = typeVariable.getBounds();
assertLenghtOne(bounds);
assertEquals(Object.class, bounds[0]);
}
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
}
}
public static Class getGenericClass(ParameterizedType parameterizedType, int i) {
Type genericClass = parameterizedType.getActualTypeArguments()[i];
if (genericClass instanceof ParameterizedType) { // 处理多级泛型
return (Class) ((ParameterizedType) genericClass).getRawType();
} else if (genericClass instanceof GenericArrayType) { // 处理数组泛型
return (Class) ((GenericArrayType) genericClass).getGenericComponentType();
} else if (genericClass instanceof TypeVariable) { // 处理泛型擦拭对象
return getClass(((TypeVariable) genericClass).getBounds()[0], 0);
} else {
return (Class) genericClass;
}
}
private static HashMap<String,Type[]> findTypeOffsets(Class<?> me, Class<?>[] decTypes){
HashMap<String,Type[]> origBindingOffsetLocation = new HashMap<String, Type[]>();
int decLenCur=1;
for(TypeVariable<?> tv : me.getTypeParameters()){
int startLoc = decLenCur;
if(decLenCur >= decTypes.length){
return null;//oops off the end, malformed list
}
int cons = slotsConsumed(decTypes[decLenCur], decTypes, decLenCur);
if(cons==-1){
return null;//failure
}
decLenCur += cons;
Class<?>[] typeDef = new Class<?>[cons];
System.arraycopy(decTypes, startLoc, typeDef, 0, cons);
origBindingOffsetLocation.put(tv.getName(), typeDef);
}
if(decLenCur != decTypes.length){
return null;//definition list is wrong length as qualification
}
return origBindingOffsetLocation;
}
/** If the class is parameterized, such as ArrayList, this returns ArrayList<E>. */
@Override
Type getGenericReturnType() {
Class<?> declaringClass = getDeclaringClass();
TypeVariable<?>[] typeParams = declaringClass.getTypeParameters();
if (typeParams.length > 0) {
return Types.newParameterizedType(declaringClass, typeParams);
} else {
return declaringClass;
}
}
/**
* {@inheritDoc}
*
* {@code [<E>]} will be returned for ArrayList's constructor. When both the class and the
* constructor have type parameters, the class parameters are prepended before those of the
* constructor's. This is an arbitrary rule since no existing language spec mandates one way or
* the other. From the declaration syntax, the class type parameter appears first, but the call
* syntax may show up in opposite order such as {@code new <A>Foo<B>()}.
*/
@Override
public final TypeVariable<?>[] getTypeParameters() {
TypeVariable<?>[] declaredByClass = getDeclaringClass().getTypeParameters();
TypeVariable<?>[] declaredByConstructor = constructor.getTypeParameters();
TypeVariable<?>[] result = new TypeVariable<?>[declaredByClass.length + declaredByConstructor.length];
System.arraycopy(declaredByClass, 0, result, 0, declaredByClass.length);
System.arraycopy(declaredByConstructor, 0, result, declaredByClass.length, declaredByConstructor.length);
return result;
}
final Type resolve(final TypeVariable<?> var) {
final TypeTable unguarded = this;
TypeTable guarded = new TypeTable() {
@Override
public Type resolveInternal(TypeVariable<?> intermediateVar, TypeTable forDependent) {
if (intermediateVar.getGenericDeclaration().equals(var.getGenericDeclaration())) {
return intermediateVar;
}
return unguarded.resolveInternal(intermediateVar, forDependent);
}
};
return resolveInternal(var, guarded);
}
/**
* return the raw type of type
*
* @param type the type
* @return raw type
*/
Class<?> getRawType(Type type) {
if (type == null) throw new NullPointerException("type == null");
if (type instanceof Class<?>) {
// Type is a normal class.
return (Class<?>) type;
}
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
// I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
// suspects some pathological case related to nested classes exists.
Type rawType = parameterizedType.getRawType();
if (!(rawType instanceof Class)) throw new IllegalArgumentException();
return (Class<?>) rawType;
}
if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();
}
if (type instanceof TypeVariable) {
// We could use the variable's bounds, but that won't work if there are multiple. Having a raw
// type that's more general than necessary is okay.
return Object.class;
}
if (type instanceof WildcardType) {
return getRawType(((WildcardType) type).getUpperBounds()[0]);
}
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
}
private 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;
}
/**
* Replace all {@link TypeVariable} into {@link ExplicitTypeVariable} to preserve variables.
* This may be required because in many places type variables are resolved into raw declaration bound.
* For example, useful for {@link TypesWalker} api.
*
* @param type type possibly containing variables
* @return same type if it doesn't contain variables or type with all {@link TypeVariable} replaced by
* {@link ExplicitTypeVariable}
* @see #resolveAllTypeVariables(Type, Map) to replace explicit varaibles
*/
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
public static Type preserveVariables(final Type type) {
final List<TypeVariable> vars = GenericsUtils.findVariables(type);
if (vars.isEmpty()) {
return type;
}
final Map<String, Type> preservation = new HashMap<String, Type>();
for (TypeVariable var : vars) {
preservation.put(var.getName(), new ExplicitTypeVariable(var));
}
// replace TypeVariable to ExplicitTypeVariable
return GenericsUtils.resolveTypeVariables(type, preservation);
}
/**
* Returns true if {@code type} is a {@code TypeVariable} with the same name and declared by the
* same {@code GenericDeclaration}.
*/
boolean equalsType(Type type) {
if (type instanceof TypeVariable) {
return equalsTypeVariable((TypeVariable<?>) type);
} else {
return false;
}
}
/**
* 检查指定的类型
*
* <pre>
* 不能有擦拭类型和通配类型
* </pre>
*
* @param type
* @return
*/
static boolean checkType(Type type) {
if (type instanceof ParameterizedType) {
// 泛型类型
ParameterizedType parameterizedType = (ParameterizedType) type;
if (!checkType(parameterizedType.getRawType())) {
return false;
}
for (Type value : parameterizedType.getActualTypeArguments()) {
if (!checkType(value)) {
return false;
}
}
} else if (type instanceof TypeVariable) {
// 擦拭类型
return false;
} else if (type instanceof GenericArrayType) {
// 数组类型
GenericArrayType genericArrayType = (GenericArrayType) type;
if (!checkType(genericArrayType.getGenericComponentType())) {
return false;
}
} else if (type instanceof WildcardType) {
// 通配类型
return false;
} else if (type instanceof Class) {
return true;
}
return true;
}
private int typeVarIndex() {
TypeVariable<?>[] tVars = getGenericDeclaration().getTypeParameters();
int i = -1;
for (TypeVariable<?> v : tVars) {
i++;
if (equals(v))
return i;
}
return -1;
}
private static Map<String, Type> matchVariables(final TypeVariable declared,
final Type known,
final Map<String, Type> tracedRootGenerics) {
final Map<String, Type> res = new HashMap<String, Type>();
// lookup variable declaration for variables (e.g. T extends List<K>)
for (Type decl : declared.getBounds()) {
// the case: A extends B: when we know A we can't tell anything about B!
if (decl instanceof TypeVariable) {
continue;
}
final Map<String, Type> match = TypeVariableUtils.matchVariableNames(
TypeVariableUtils.preserveVariables(decl), known);
// check if found match is more specific then already resolved
for (Map.Entry<String, Type> matchEntry : match.entrySet()) {
final String name = matchEntry.getKey();
final Type value = matchEntry.getValue();
if (tracedRootGenerics.containsKey(name)) {
final Type stored = tracedRootGenerics.get(name);
if (!TypeUtils.isMoreSpecific(value, stored)) {
// do nothing with type
continue;
}
}
tracedRootGenerics.put(name, value);
res.put(name, value);
}
}
return res;
}