簡體   English   中英

如何基於Java中的類參數實例化泛型類

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM