当参数化类型通过层次结构时,在Java中创建泛型类型的实例? [英] Create instance of generic type in Java when parameterized type passes through hierarchies?
问题描述
我一直在阅读这个问题的答案:
我已经实现了Lars Bohl提出的方法。我修改了他的代码,如下所示:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class ParameterizedTypeEg< E> {
public Class< E> getTypeParameterClass(){
类型type = getClass()。getGenericSuperclass();
ParameterizedType paramType =(ParameterizedType)类型;
return(Class< E>)paramType.getActualTypeArguments()[0];
}
private static class StringHome extends ParameterizedTypeEg< String> {
private String _string;
StringHome(String string){
_string = string;
$ b $ public static void main(String [] args)
throws InstantiationException,IllegalAccessException {
String str = new StringHome(my string)。getTypeParameterClass ().newInstance();
String str2 = new ParameterizedTypeEg< String>()。getTypeParameterClass()。newInstance();
$ b 这种方法对于str变量很有效。然后str2被创建,看起来是相同的类型(ParameterizedTypeEg< String>,它与StringHome基本相同)。然而,这种方法不适用于str2,并且当我尝试转换(ParameterizedType)类型时抛出了ClassCastException。
即使对于str2,我也参数化了ParameterizedTypeEg一个String,getGenericSuperclass()返回的东西与str非常不同。此外,在方法str2中将'this'显示为ParameterizedTypeEg,而对于str,'this'是ParameterizedTypeEg $ StringHome。我想这是问题的根源。为什么Java没有看到str2的泛型类型也被确定了?
当参数化类型通过多个级别时,我看到了同样的问题层次?也就是说,B类T>包含A< T>并且我实例化了一个B.在A中,我不能通过使用上面的方法确定A的参数化类型来创建一个String对象。该方法也会在遏制层次结构中产生异常。这导致我一个问题,因为我希望能够通过多层次的遏制和/或继承来传递参数化类型,并且在所有情况下都有相同的方法生成泛型类型的实例。
感谢,
John
解决方案 p>
from
String str2 = new ParameterizedTypeEg< String>()。getTypeParameterClass ().newInstance();
至
String str2 = new ParameterizedTypeEg< String>(){}。getTypeParameterClass()。newInstance();
这将创建ParameterizedTypeEg的匿名子类。当你调用
getClass()。getGenericSuperclass();
在StringHome上,你得到一个ParameterizedTypeEg< java.lang.String>,这就是你想要的。如果你创建了str2,那么这个调用只是返回Object,所以试图将其转换为paremeterized类型将失败:
异常线程mainjava.lang.ClassCastException:
java.lang.Class不能转换为java.lang.reflect.ParameterizedType
创建一个匿名子类使得这个返回ParameterizedTypeEg< java.lang.String>
这与在Google Guice Guave库中键入Token 类,顺便说一句。你写的,例如
new TypeToken< List< String>>(){}
$ c
$ b $ p $ 新TypeToken< / p> List< String>>()
I have been reading the answers to the question:
Create instance of generic type in Java?
I have implemented the approach suggested by Lars Bohl. I adapted his code as follows:
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class ParameterizedTypeEg<E> {
public Class<E> getTypeParameterClass() {
Type type = getClass().getGenericSuperclass();
ParameterizedType paramType = (ParameterizedType) type;
return (Class<E>) paramType.getActualTypeArguments()[0];
}
private static class StringHome extends ParameterizedTypeEg<String> {
private String _string;
StringHome (String string) {
_string = string;
}
}
public static void main(String[] args)
throws InstantiationException, IllegalAccessException {
String str = new StringHome("my string").getTypeParameterClass().newInstance();
String str2 = new ParameterizedTypeEg<String>().getTypeParameterClass().newInstance();
}
}
This approach works fine for the str variable. Then str2 is created with what appears to me to be the same type (ParameterizedTypeEg < String >, which is basically the same thing as a StringHome). However, the approach does not work for str2, and a ClassCastException is thrown when I try to cast (ParameterizedType) type.
Even though for str2, I have parameterized ParameterizedTypeEg with a String, getGenericSuperclass() returns something very different than for str. Also, within methods str2 shows 'this' as a ParameterizedTypeEg, whereas for str, 'this' is a ParameterizedTypeEg$StringHome. I suppose that is the root of the problem. Why does Java not see that the generic type has been determined for str2 also?
I have had what appears to be the same problem when the parameterized type is passed through multiple levels of hierarchy? That is, class B< T > contains A< T > and I instantiate a B. Within A, I cannot create a String object by determining the parameterized type of A using the above approach. The approach produces an exception in the case of a containment hierarchy as well. And this causes me a problem because I want to be able to pass the parameterized type through multiple levels of containment and/or inheritance and have the same approach produce an instance of the generic type in all cases.
Thanks,
John
解决方案 With the following change your code will work:
from
String str2 = new ParameterizedTypeEg<String>().getTypeParameterClass().newInstance();
to
String str2 = new ParameterizedTypeEg<String>(){}.getTypeParameterClass().newInstance();
This creates an anonymous subclass of ParameterizedTypeEg. When you call
getClass().getGenericSuperclass();
on StringHome, you get a ParameterizedTypeEg < java.lang.String>, which is what you want. If you create str2 as you did, that call simply returns Object, so the attempt to cast it to a paremeterized type fails:
Exception in thread "main" java.lang.ClassCastException:
java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
Creating an anonymous subclass makes this return ParameterizedTypeEg < java.lang.String>
This is the same trick that's used in the Type Token class in the Google Guice Guave libraries, btw. You write, for example
new TypeToken<List<String>>() {}
and not
new TypeToken<List<String>>()
这篇关于当参数化类型通过层次结构时,在Java中创建泛型类型的实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!