Это будет делать то, что вы пытаетесь сделать, обеспечивая безопасность типов. Нет способа избежать неконтролируемого предупреждения, но проверка типов, выполненная здесь, оправдывает его подавление.
public static void main(String[] args)
throws Exception
{
Class<? extends Creator<String>> clz = load(argv[0], String.class);
Constructor<? extends Creator<String>> ctor = clz.getConstructor();
Creator<String> creator = ctor.newInstance();
System.out.println(creator.create());
}
public static <T> Class<? extends Creator<T>> load(String fqcn, Class<T> type)
throws ClassNotFoundException
{
Class<?> any = Class.forName(fqcn);
for (Class<?> clz = any; clz != null; clz = clz.getSuperclass()) {
for (Object ifc : clz.getGenericInterfaces()) {
if (ifc instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) ifc;
if (Creator.class.equals(pType.getRawType())) {
if (!pType.getActualTypeArguments()[0].equals(type))
throw new ClassCastException("Class implements " + pType);
/* We've done the necessary checks to show that this is safe. */
@SuppressWarnings("unchecked")
Class<? extends Creator<T>> creator = (Class<? extends Creator<T>>) any;
return creator;
}
}
}
}
throw new ClassCastException(fqcn + " does not implement Creator<String>");
}
Основное ограничение, которое вы должны соблюдать, заключается в том, что класс в иерархии должен указывать параметр типа. Например class MyCreator implements Creator<String>
. Вы не можете использовать его с class GenericCreator<T> implements Creator<T>
.
В настоящее время он не обрабатывает допустимый случай, когда вы создаете новый интерфейс interface StringCreatorIfc extends Creator<String>
и имеете класс, реализующий это. Это можно улучшить, но я оставлю это как упражнение для склонных.