Atm*_*ons 5 java generics type-erasure
我有一个方法返回一个List<Property<?>>.
属性是具有一个通用参数的类型:
public class Property<T extends Comparable<T>> { ... }
Run Code Online (Sandbox Code Playgroud)
有一个混合类型属性的列表,我不知道具体元素具有什么类型参数.
我想做那样的事情:
List<Property<?>> list = getList();
for(Property<?> crt : list)
{
PropertyWrapper<?> crtWrapper = new PropertyWrapper(crt.getGenericType());
// I know this doesn't exist ----^
}
Run Code Online (Sandbox Code Playgroud)
在一句话中:我需要PropertyWrapper具有与当前相同的通用模板参数Property.有没有办法做到这一点?
我可以应用/sf/answers/240655131/中所述的建议,但即使我这样做,如何实现适当的,PropertyWrapper<XXX>然后只有一个实例Class<T>?
Property<?>如果需要,我可以修改.我也不介意是否需要使用反射(我认为它需要)
编辑:我忘记了什么.事实上,我无法通过线路实现包装
PropertyWrapper<?> crtWrapper = new PropertyWrapper(crt.getGenericType());
Run Code Online (Sandbox Code Playgroud)
因为我有专门的子类(PropertyWrapper_String).
现在我看到两种可能性:
1:按字符串对类进行Instanciate:
String strGenericType = "";
Class<?> wrapperClass = Class.forName("PropertyWrapper_" + strGenericType);
Run Code Online (Sandbox Code Playgroud)
2:有没有办法在不创建子类的情况下专门化泛型类?
非常感谢您的提示
尝试创建以下方法:
<T> PropertyWrapper<T> createWrapper(Property<T> property){
return new PropertyWrapper<T>(property);
}
Run Code Online (Sandbox Code Playgroud)
然后这样称呼它.
List<Property<?>> list = getList();
for(Property<?> crt : list)
{
PropertyWrapper<?> crtWrapper = createWrapper(crt);
}
Run Code Online (Sandbox Code Playgroud)
上述工作的原因是泛型类型T是从参数推断出来的,并且对整个方法都是锁定的.与<?>在循环中使用不同,其中每个实例<?>被推断为不同类型.
编辑:
要根据包装器中的类来处理具有不同类类型的问题,请考虑一个Map,其中键是要包装的类,值是包装器.
Map<Class<?>, Class<?>> myMap;
Run Code Online (Sandbox Code Playgroud)
那么你可以这样:
Class<?> wrappedType = property.getGenericType();
Class<?> wrapperClass = myMap.get(wrappedType);
PropertyWrapper<?> wrapper = (PropertyWrapper<?>) wrapperClass.newInstance();
Run Code Online (Sandbox Code Playgroud)
虽然如果需要传递参数,可能需要执行类似的操作.
Constructor<?> constructor = wrapperClass.getDeclaredConstructor(property.getClass());
PropertyWrapper<?> wrapper = (PropertyWrapper<?>) constructor.newInstance(property);
Run Code Online (Sandbox Code Playgroud)
好吧,我自己来回答一下。
我现在将 的实例传递Class<?>给Property-class。
然后,我提取属性的基本名称,并简单地将其删除,"java.lang."这可能与大多数情况一样,我对原始数据类型执行此操作 - 分别是。他们的自动装箱课程。
此外,我只是按名称实例化包装器的新实例,并将要包装的属性作为参数传递给适用于此的构造函数。
这里有一些代码供你们感兴趣的人使用:
String template = "..."; // some package definition
for (Property<?> crt : bag)
{
String className = template + crt.getClassName();
Class<? extends PropertyWrapper<?>> wrapperClass = null;
wrapperClass = (Class<? extends PropertyWrapper<?>>) Class.forName(className);
Constructor<? extends PropertyWrapper<?>> constructor = wrapperClass.getConstructor(new Class<?>[] {Property.class});
PropertyWrapper<?> wrapper = constructor.newInstance(crt);
// Further operations using the wrapper
}
Run Code Online (Sandbox Code Playgroud)
为了简单起见,我省略了错误处理部分。