如何基于类参数实例化新的泛型类? 我的主要课程如下:
public class ServiceTransformer<SERVICE_I, SERVICE_O> extends Loggable {
private Class<SERVICE_I> serviceInputClass;
private Class<SERVICE_O> serviceOutputClass;
public ServiceTransformer(Logger logger, String inputXslt, String outputXslt, String appRoot) {
try {
serviceInputClass = (Class<SERVICE_I>) getGenericTypeClass(0);
serviceOutputClass = (Class<SERVICE_O>) getGenericTypeClass(1);
} catch (BadConfigurationException ex) {
LOGGER.error("@@@ ConfigBase() Constructor Exception => ", ex);
} catch (MalformedURLException ex) {
LOGGER.error("@@@ ConfigBase() Constructor Exception => ", ex);
}
}
private Type getGenericTypeClass(int index) {
try {
return ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[index];
} catch (Exception ex) {
LOGGER.error("@@@ getGenericTypeClass() Exception => ", ex);
}
return null;
}
}
我实例化一个新的ServiceTransformer
类,如下所示:
ServiceTransformer<ReactivatePrepaidSubscriberInput, ReactivatePrepaidSubcriberOutput> service =
new ServiceTransformer<ReactivatePrepaidSubscriberInput, ReactivatePrepaidSubcriberOutput>(
LOGGER, inputFile, outputFile, APPROOT);
我目前收到的错误是java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
不知道我哪里出错了。
答案 0 :(得分:3)
只能从超类中获取泛型类型参数,就像你在做它一样:
return ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()
但是您的ServiceTransformer
不会扩展通用类,只会扩展Loggable
,这不是通用的,因此无法转换为ParameterizedType
。
你可以做的伎俩是实例化ServiceTransformer
的匿名子类:
new ServiceTransformer<In, Out>(LOGGER, inputFile, outputFile, APPROOT) {};
(注意最后的{}
)
这将允许访问超类的泛型类型参数 - 这次超类是ServiceTransformer
类本身。
但是,请注意,每次使用此匿名类构造时,编译器都会创建一个新类,这可能会影响应用程序的性能。
如果您经常使用一组固定的<In, Out>
类型,请为其创建适当的顶级命名子类,并按照其他答案的建议重复使用。例如。
class StringIntTransformer extends ServiceTransformer<String, Integer>
如果您经常使用该组合。
答案 1 :(得分:0)
主要问题是泛型类型参数只能从继承上下文中检索,您可以从方法名称中清楚地看到它:
1 => [{"foo":1,"bar":23},{"foo":1,"bar":25}]
2 => [{"foo":2,"bar":24},{"foo":2,"bar":26},{"foo":2,"bar":27}]
3 => [{"foo":3,"bar":29}]
这意味着您需要实例化getGenericSuperclass()
的子类型才能查询类型参数。
这可以通过两种方式完成,您可以将自定义实际类型设为
ServiceTransformer<I,O>
或者您可以匿名定义:
public static class MyServiceTransformer extends ServiceTransformer<ReactivatePrepaidSubscriberInput,ReactivatePrepaidSubcriberOutput>
{
MyServiceTransformer()
{
super(...);
}
}
答案 2 :(得分:0)
首先,您需要更深层次的继承。
public abstract class AbstractServiceTransformer<SERVICE_I, SERVICE_O> extends Loggable {
private Class<SERVICE_I> serviceInputClass;
private Class<SERVICE_O> serviceOutputClass;
public ServiceTransformer(Logger logger, String inputXslt, String outputXslt, String appRoot) {
serviceInputClass = TypeUtils.getParametrizedType(this.getClass(),0)
serviceOutputClass = TypeUtils.getParametrizedType(this.getClass(),1)
}
...
}
然后是你的实际实现。
public class ServiceTransformer extends AbstractServiceTransformer<Service1, Service2> {
...
}
之后,您可以读取类似参数类。
public final class TypeUtils {
/**
* Returns parameterized type as a Class.
*/
public static <T> Class<T> getParametrizedType(Class<?> baseClass, int index) {
final Type genericSuperClass = baseClass.getGenericSuperclass();
if (!(genericSuperClass instanceof ParameterizedType)) {
throw new IllegalArgumentException("Your super class need to have a parameterized type");
}
final ParameterizedType parameterizedType = (ParameterizedType) genericSuperClass;
final Type[] types = parameterizedType.getActualTypeArguments();
if (types[index] instanceof Class<?>) {
return (Class<T>) types[index];
} else {
throw new IllegalArgumentException("Parameter type is mismatched");
}
}
}