Java tutorial
/* * Copyright 2008-2010 the T2 Project ant the Others. * * 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 org.t2framework.commons.util; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class GenericsUtil { public static Class<?> getActualClass(Type type, Class<?> targetClass) { Map<TypeVariable<?>, Type> map = getTypeVariableMap(targetClass); return getActualClass(type, map); } public static Type getActualType(Type type, Class<?> targetClass) { Map<TypeVariable<?>, Type> map = getTypeVariableMap(targetClass); return getActualType(type, map); } private static Class<?> getActualClass(Type type, Map<TypeVariable<?>, Type> map) { if (Class.class.isInstance(type)) { return Class.class.cast(type); } if (ParameterizedType.class.isInstance(type)) { final Type actualType = getActualType(type, map); return getActualClass(actualType, map); } else if (TypeVariable.class.isInstance(type)) { final Type actualType = getActualType(type, map); return getActualClass(actualType, map); } else if (GenericArrayType.class.isInstance(type)) { GenericArrayType genericArrayType = GenericArrayType.class.cast(type); final Type genericComponentType = genericArrayType.getGenericComponentType(); Class<?> componentClass = getActualClass(genericComponentType, map); return Array.newInstance(componentClass, 0).getClass(); } else { return null; } } private static Type getActualType(Type type, Map<TypeVariable<?>, Type> map) { if (Class.class.isInstance(type)) { return type; } else if (ParameterizedType.class.isInstance(type)) { return ParameterizedType.class.cast(type).getRawType(); } else if (TypeVariable.class.isInstance(type)) { return map.get(TypeVariable.class.cast(type)); } else { return null; } } private static Map<TypeVariable<?>, Type> getTypeVariableMap(final Class<?> clazz) { if (clazz == null) { return Collections.emptyMap(); } final Map<TypeVariable<?>, Type> map = new LinkedHashMap<TypeVariable<?>, Type>(); final Class<?> superClass = clazz.getSuperclass(); final Type superClassType = clazz.getGenericSuperclass(); if (superClass != null) { gatherTypeVariables(superClass, superClassType, map); } final Class<?>[] interfaces = clazz.getInterfaces(); final Type[] interfaceTypes = clazz.getGenericInterfaces(); for (int i = 0; i < interfaces.length; ++i) { gatherTypeVariables(interfaces[i], interfaceTypes[i], map); } return map; } private static void gatherTypeVariables(final Class<?> clazz, final Type type, final Map<TypeVariable<?>, Type> map) { if (clazz == null) { return; } gatherTypeVariables(type, map); final Class<?> superClass = clazz.getSuperclass(); final Type superClassType = clazz.getGenericSuperclass(); if (superClass != null) { gatherTypeVariables(superClass, superClassType, map); } final Class<?>[] interfaces = clazz.getInterfaces(); final Type[] interfaceTypes = clazz.getGenericInterfaces(); for (int i = 0; i < interfaces.length; ++i) { gatherTypeVariables(interfaces[i], interfaceTypes[i], map); } } private static void gatherTypeVariables(final Type type, final Map<TypeVariable<?>, Type> map) { if (ParameterizedType.class.isInstance(type)) { final ParameterizedType parameterizedType = ParameterizedType.class.cast(type); final TypeVariable<?>[] typeVariables = GenericDeclaration.class.cast(parameterizedType.getRawType()) .getTypeParameters(); final Type[] actualTypes = parameterizedType.getActualTypeArguments(); for (int i = 0; i < actualTypes.length; ++i) { map.put(typeVariables[i], actualTypes[i]); } } } }