You cannot do this in a safe way without changing the downstream code ( context.get() ), because the generic type is erased at runtime. In fact, the clazz argument clazz not currently used at all: you can simply delete this argument and the method will execute identically, since the cast to (T) is currently no-op due to erasure. Your current code is not type safe even for non-class classes.
So, if you do not care about security and just want to avoid being cast into the client code, you can simply delete the last argument and turn off warnings for the method once.
If you want a security type, you can use super-type tokens to preserve general type information: Guava TypeToken works and is easily accessible (IMO every Java project should use Guava already).
However, your code will require changes in the opposite direction, since you need to capture the type information when adding objects and check it when exiting. You haven't shared the code for your Context class, so it's hard to say if this is possible, but in any case you need something like this:
static class TypedParam { final TypeToken<?> type; final Object object; private TypedParam(TypeToken<?> type, Object object) { this.type = type; this.object = object; } } public static class Context { Map<String, TypedParam> params = new HashMap<>(); TypedParam get(String name) { return params.get(name); } } public static <T> T getParameter(final Context context, final String name, final TypeToken<T> type) { TypedParam param = context.get(name); if (type.isAssignableFrom(param.type)) { @SuppressWarnings("unchecked") T ret = (T)param.object; return ret; } else { throw new ClassCastException(param.type + " cannot be assigned to " + type); } }
Basically, you know the general type of all objects in your parameter map and check with a "well-known throw" at runtime. I did not include Context.put() above, but you would need to write down the type information when adding the parameter.
You still have @SuppressWarnings("unchecked") , but here it is type safe because you maintain type information (in the guts of many generic classes you will find reliable throws so they cannot always be avoided even in the right code).
BeeOnRope
source share