[英]How to instantiate a generic class based on class parameters in Java
如何基於類參數實例化新的泛型類? 我的主要課程如下:
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
不知道我哪里錯了。
它只能從超類中獲取泛型類型參數,就像您在執行它一樣:
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>
如果你經常使用這種組合。
主要問題是泛型類型參數只能從繼承上下文中檢索,您可以從方法名稱中清楚地看到它:
getGenericSuperclass()
這意味着您需要實例化ServiceTransformer<I,O>
的子類型才能查詢類型參數。
這可以通過兩種方式完成,您可以使用自定義實際類型
public static class MyServiceTransformer extends ServiceTransformer<ReactivatePrepaidSubscriberInput,ReactivatePrepaidSubcriberOutput>
{
MyServiceTransformer()
{
super(...);
}
}
或者您可以匿名定義它:
new ServiceTransformer<ReactivatePrepaidSubscriberInput, ReactivatePrepaidSubcriberOutput>(....){}
首先,您需要更深層次的繼承。
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");
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.