package de.tutorials;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
*/
/**
* @author Thomas.Darimont
*
*/
public class GenericTypeDetectionExample {
/**
* @param args
*/
public static void main(String[] args) {
List<String> list = new ArrayList<String>() {
};
System.out.println(((ParameterizedType) list.getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]);
List<String> listA = createList();
System.out.println(((ParameterizedType) listA.getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]);
String string = create();
System.out.println(System.identityHashCode(string));
System.out.println(new TypeVariable<String>() {
}.getType());
System.out.println(getParameterTypesFromInterface(new Service(),
IService.class));
}
private static Map<String, Class<?>> getParameterTypesFromInterface(
Object target, Class<?> iface) {
Map<String, Class<?>> parameterNameToTypeMap = new HashMap<String, Class<?>>();
Class<?> targetClass = target.getClass();
for (Method ifaceMethod : iface.getMethods()) {
Type ifaceMethodGenericReturnType = ifaceMethod
.getGenericReturnType();
Type[] ifaceMethodGenericParameterTypes = ifaceMethod
.getGenericParameterTypes();
Method targetMethod = findMostSpecificDeclaredMethodBy(ifaceMethod,
targetClass);
Type targetMethodGenericReturnType = targetMethod
.getGenericReturnType();
Type[] targetMethodGenericParameterTypes = targetMethod
.getGenericParameterTypes();
System.out.println(ifaceMethod);
String parameterName = null;
if (null != targetMethodGenericReturnType) {
parameterName = ifaceMethodGenericReturnType.toString();
parameterNameToTypeMap.put(parameterName,
(Class<?>) targetMethodGenericReturnType);
}
for (int i = 0; i < ifaceMethodGenericParameterTypes.length; i++) {
parameterName = ifaceMethodGenericParameterTypes[i].toString();
Type genericParameterType = targetMethodGenericParameterTypes[i];
if (genericParameterType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
System.out.println(parameterizedType
.getActualTypeArguments());
}
parameterNameToTypeMap.put(parameterName,
(Class<?>) genericParameterType);
}
}
return parameterNameToTypeMap;
}
private static Method findMostSpecificDeclaredMethodBy(Method ifaceMethod,
Class<?> targetClass) {
Method targetMethod = null;
Class<?>[] ifaceMethodParameterTypes = ifaceMethod.getParameterTypes();
for (Method method : targetClass.getDeclaredMethods()) {
Class<?>[] methodParameterTypes = method.getParameterTypes();
boolean match = true;
if (method.getName().equals(ifaceMethod.getName())
&& ifaceMethod.getReturnType().isAssignableFrom(
method.getReturnType())
&& methodParameterTypes.length == ifaceMethodParameterTypes.length) {
for (int i = 0; i < methodParameterTypes.length; i++) {
if (!ifaceMethodParameterTypes[i]
.isAssignableFrom(methodParameterTypes[i])) {
match = false;
}
}
if (!match) {
continue;
}
if (!method.isSynthetic()) {
targetMethod = method;
break;
}
}
}
return targetMethod;
}
private static <T> List<T> createList() {
return new ArrayList<T>() {
};
}
private static <T> T create(T... t) {
try {
return (T) t.getClass().getComponentType().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
static class TypeVariable<T> {
Class<T> type;
public TypeVariable() {
this.type = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public Class<T> getType() {
return type;
}
}
static interface IService<TResponse, TRequest> {
TResponse process(TRequest request);
}
static class Service implements IService<Integer, String> {
@Override
public Integer process(String request) {
System.out.println("Processing: " + request);
return request.length();
}
}
}