diff --git a/src/main/java/org/cobbzilla/util/reflect/ReflectionUtil.java b/src/main/java/org/cobbzilla/util/reflect/ReflectionUtil.java index 0f90f48..271cacd 100644 --- a/src/main/java/org/cobbzilla/util/reflect/ReflectionUtil.java +++ b/src/main/java/org/cobbzilla/util/reflect/ReflectionUtil.java @@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.beanutils.MethodUtils; import org.apache.commons.collections.Transformer; import org.apache.commons.lang3.ArrayUtils; +import org.cobbzilla.util.collection.ExpirationEvictionPolicy; import org.cobbzilla.util.collection.ExpirationMap; import org.cobbzilla.util.string.StringUtil; @@ -705,19 +706,22 @@ public class ReflectionUtil { */ public static Class getFirstTypeParam(Class clazz) { return getTypeParam(clazz, 0); } + private static Map typeParamCache = new ExpirationMap<>(ExpirationEvictionPolicy.atime); + public static Class getTypeParam(Class clazz, int index) { - // todo: add a cache on this thing... could do wonders - Class check = clazz; - while (check.getGenericSuperclass() == null || !(check.getGenericSuperclass() instanceof ParameterizedType)) { - check = check.getSuperclass(); - if (check.equals(Object.class)) die("getTypeParam("+clazz.getName()+"): no type parameters found"); - } - final ParameterizedType parameterizedType = (ParameterizedType) check.getGenericSuperclass(); - final Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); - if (index >= actualTypeArguments.length) die("getTypeParam("+clazz.getName()+"): "+actualTypeArguments.length+" type parameters found, index "+index+" out of bounds"); - if (actualTypeArguments[index] instanceof Class) return (Class) actualTypeArguments[index]; - if (actualTypeArguments[index] instanceof ParameterizedType) return (Class) ((ParameterizedType) actualTypeArguments[index]).getRawType(); - return (Class) ((Type) actualTypeArguments[index]).getClass(); + return (Class) typeParamCache.computeIfAbsent(clazz.getName()+":"+index, k -> { + Class check = clazz; + while (check.getGenericSuperclass() == null || !(check.getGenericSuperclass() instanceof ParameterizedType)) { + check = check.getSuperclass(); + if (check.equals(Object.class)) die("getTypeParam("+clazz.getName()+"): no type parameters found"); + } + final ParameterizedType parameterizedType = (ParameterizedType) check.getGenericSuperclass(); + final Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + if (index >= actualTypeArguments.length) die("getTypeParam("+clazz.getName()+"): "+actualTypeArguments.length+" type parameters found, index "+index+" out of bounds"); + if (actualTypeArguments[index] instanceof Class) return (Class) actualTypeArguments[index]; + if (actualTypeArguments[index] instanceof ParameterizedType) return (Class) ((ParameterizedType) actualTypeArguments[index]).getRawType(); + return ((Type) actualTypeArguments[index]).getClass(); + }); } /**