我正试图为一个用泛型类型参数参数化的类拉出一些Guava TypeToken
魔法,但是当我试图通过{{1}实例化时,我得到了ClassNotFoundException
方法。
Class.forName(String)
我得到了这个例外:
“无法找到public class EnumeratedMenu<E extends Enum<E>,T extends EnumeratedBean<E>> {
private final TypeToken<EnumeratedMenu<E,T>> typeToken =
new TypeToken<EnumeratedMenu<E,T>>(getClass()) { };
private Class<T> getBean() {
TypeToken<?> genericBeanParam = typeToken.resolveType(EnumeratedMenu.class.getTypeParameters()[1]);
try {
//This generates a ClassNotFoundException because of the generic type parameter that EnumeratedBean has.
return (Class<T>)Class.forName(genericBeanParam.getType().getTypeName());
} catch(ClassNotFoundException e) {
log.error("Unable to find the class definition for {}", genericBeanParam.getType().getTypeName());
log.catching(e);
}
}
}
”
EnumeratedBean<ContextMenuOption$ContextType>
是ContextMenuOption$ContextType
的通用enum
参数的运行时类型。我如何获得我想要的类对象?
澄清:
我需要构造类的实例以与构建器对象一起使用,该构建器对象将构造如下所示的菜单选项:
EnumeratedBean
答案 0 :(得分:4)
你到底想要做什么?
您永远无法获得代表Class<T>
等通用类型的EnumeratedBean<ContextMenuOption$ContextType>
对象,因为Class
只能代表{{1}这样的原始类型}}
可能有其他方法可以达到您想要的结果,但目前还不清楚您想要的结果。例如,您想要使用EnumeratedBean
返回的内容是什么?也许可以在没有中间Class
对象的情况下 。
修改强>
由于看起来您想要的是能够创建Class
的实例,以下是使用T
进行操作的示例:
TypeToken
答案 1 :(得分:1)
这是不可能的,因为总是只有一个Class
,无论参数化如何。这就是Java泛型如何使用类型擦除。
有关如何以及为何的详细说明,您可能需要阅读:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html
但是对于实例化,你只需要使用你已经拥有的Class
;并按照你想要的方式转换泛型类型签名。
这意味着,例如,您实际上可以这样做:
List<String> strings = new ArrayList<String>();
List<Integer> numbers = (List<Integer>)(List<?>) strings;
numbers.add(Integer.valueOf(12));
没有运行时异常。没有真正的运行时信息限制内容;只有隐式投射。但是,如果您尝试过,则会收到运行时异常:
String str = strings.get(0);
因为虽然基础List
乐意接受任何java.lang.Object
,但访问代码具有“隐藏”强制转换,这将触发异常。
因此,实例化可能会起作用:
List<String> s = (List<String>) ArrayList.class.newInstance();
但使用你想要的任何通用类型。
编辑:
如果需要Guava的TypeToken
,它的javadocs建议您应该使用getRawType()
获取原始类,或者使用constructor()
直接创建实例。