К сожалению решение Кристофа как написано работает только в очень ограниченных обстоятельствах , [EDIT: как уже было сказано ниже, я больше не помню свои рассуждения для этого предложения, и это, скорее всего, неверно: «Обратите внимание, что это будет работать только в абстрактных классах, в первую очередь».] Следующая трудность состоит в том, что g()
работает только с подклассами DIRECT A
. Мы можем это исправить:
private Class<?> extractClassFromType(Type t) throws ClassCastException {
if (t instanceof Class<?>) {
return (Class<?>)t;
}
return (Class<?>)((ParameterizedType)t).getRawType();
}
public Class<B> g() throws ClassCastException {
Class<?> superClass = getClass(); // initial value
Type superType;
do {
superType = superClass.getGenericSuperclass();
superClass = extractClassFromType(superType);
} while (! (superClass.equals(A.class)));
Type actualArg = ((ParameterizedType)superType).getActualTypeArguments()[0];
return (Class<B>)extractClassFromType(actualArg);
}
Это будет работать во многих ситуациях на практике, но не ВСЕ. Рассмотрим:
public class Foo<U,T extends Collection<?>> extends A<T> {}
(new Foo<String,List<Object>>() {}).g();
Это будет бросать ClassCastException
, потому что тип аргумента здесь не Class
или ParameterizedType
вообще; это TypeVariable
T
. Так что теперь вы застряли, пытаясь понять, какой тип должен был стоять T
, и так далее вниз по кроличьей дыре.
Я думаю, что единственный разумный общий ответ - это нечто похожее на первоначальный ответ Николаса - в общем, если вашему классу необходимо создать объекты другого класса, которые неизвестны во время компиляции, пользователям вашего класса необходимо пройти этот класс буквально (или, возможно, Фабрика) явно относится к вашему классу и не зависит исключительно от дженериков.
Это, безусловно, уродливо, но трюк с защищенным конструктором для меня достаточно хорош. Я использую общий класс как абстрактный класс, который служит базой от 5 до 10 конкретных классов. Благодаря! – 2008-10-08 13:36:16
Можно ли использовать это, чтобы определить, какой общий тип является объектом? например `if (obj.getClazz() является строкой) doThis(); if (obj.getClazz() - целое число) doThat(); ` – dwjohnston 2012-11-09 00:09:36
^ ` if (obj.getClazz(). Equals (String.class)) ... ` – dwjohnston 2012-11-09 01:14:32