簡體   English   中英

設計模式:Lazy Singleton,Generics和Inheritance:java.lang.Class無法強制轉換為java.lang.reflect.ParameterizedType

[英]Design Pattern: Lazy Singleton, Generics and Inheritance: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

我試圖用泛型和繼承實現Lazy Singleton。 我創建了一個abstract超類,並聲明了一個Map,它將存儲該類的子類的所有實例。

這里是:

public abstract class AbstractXMLParser<T> {
    @SuppressWarnings("rawtypes")
    private static final Map<Class<? extends AbstractXMLParser>, AbstractXMLParser> INSTANCES = new HashMap<>();

    public AbstractXMLParser() {
        throw new UnsupportedOperationException("Cannot instantiate");
    }

    private static class SingletonHolder<T> {       
        @SuppressWarnings({ "unchecked"})
        private static <T> T getInstance() throws InstantiationException, IllegalAccessException {
            Class<T> clazz = (Class<T>) ((ParameterizedType) SingletonHolder.class.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
            return clazz.newInstance();
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static <T extends AbstractXMLParser> T getInstance() throws InstantiationException, IllegalAccessException {
        Class<T> clazz = (Class<T>) ((ParameterizedType) AbstractXMLParser.class.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        if(INSTANCES.containsKey(clazz)) {
            return (T) INSTANCES.get(clazz);
        } else {
            T instance = SingletonHolder.getInstance();
            INSTANCES.put(clazz, instance);
            return instance;
        }
    }
}

其中一個兒童班是:

public class ActivityTypeXMLParser extends AbstractXMLParser<ActivityTypeXMLParser>{
    private ActivityTypesXMLModel activityTypes;

    private ActivityTypeXMLParser() {

    }

    public static void main(String... strings) throws InstantiationException, IllegalAccessException {
        ActivityTypeXMLParser.getInstance();

    }
}

main方法是用於測試目的。 但我得到例外:

Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
    at com.edfx.adb.xml.parser.AbstractXMLParser.getInstance(AbstractXMLParser.java:25)
    at com.edfx.adb.xml.parser.ActivityTypeXMLParser.main(ActivityTypeXMLParser.java:30)

現在調試后我發現了

Class<T> clazz = (Class<T>) ((ParameterizedType) AbstractXMLParser.class.getClass().getGenericSuperclass()).getActualTypeArguments()[0];

是異常的原因,因為AbstractXMLParser.class.getClass().getGenericSuperclass()返回class java.lang.Object 我需要在這里獲得Class<T> 我怎樣才能提取它的類AbstractXMLParserSingletonHolderAbstractXMLParser

此代碼存在多個問題:

  • static方法不是繼承的。 當調用ActivityTypeXMLParser.getInstance()時, AbstractXMLParser.getInstance()不知道它在ActivityTypeXMLParser上下文中被調用。

  • AbstractXMLParser.class.getClass()返回Class' of Class , not Class的Class`。

  • 目前尚不清楚為什么需要AbstractXMLParser<T>才是通用的。 請注意, AbstractXMLParserSingletonHoldergetInstance()中的T是不同的類型參數。

您需要隱式地將有問題的類傳遞給getInstance()

getInstance(ActivityTypeXMLParser.class);

@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T extends AbstractXMLParser> T getInstance(Class<T> clazz) 
    throws InstantiationException, 
    ...
}

這是我所做的完整解決方案,對某人有幫助。

abstract super-class

@SuppressWarnings({"all"})
public abstract class AbstractXMLParser<T> {    
    private static final Map<Class<? extends AbstractXMLParser>, AbstractXMLParser> INSTANCES = new HashMap<>();

    public AbstractXMLParser() {

    }

    private static class SingletonHolder<T> {               
        private static <T> T getInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
            Constructor<T> constructor = (Constructor<T>) clazz.getDeclaredConstructors()[0];
            constructor.setAccessible(true);            
            return constructor.newInstance(null);
        }
    }

    protected static <T extends AbstractXMLParser<T>> T getInstance(Class<T> clazz) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {      
        if(INSTANCES.containsKey(clazz)) {
            return (T) INSTANCES.get(clazz);
        } else {
            T instance = SingletonHolder.getInstance(clazz);
            INSTANCES.put(clazz, instance);
            return instance;
        }
    }

    protected static <T extends AbstractXMLParser<T>> void putInstance(Class<T> clazz, T instance) {
        if(!INSTANCES.containsKey(clazz)) {
            INSTANCES.put(clazz, instance);
        }
    }
}

其中一個孩子班:

public class ActivityTypeXMLParser extends AbstractXMLParser<ActivityTypeXMLParser>{

    private ActivityTypeXMLParser() {

    }   

    public static ActivityTypeXMLParser getInstance() {
        ActivityTypeXMLParser activityTypeXMLParser = null;

        try {
            activityTypeXMLParser = getInstance(ActivityTypeXMLParser.class);
        } catch (Exception exception) {
        }

        if(activityTypeXMLParser == null) {
            activityTypeXMLParser = new ActivityTypeXMLParser();
            putInstance(ActivityTypeXMLParser.class, activityTypeXMLParser);
        }

        return activityTypeXMLParser;
    }
}

您似乎想要獲取類的泛型類型,該類是抽象類的子類。 但是你得到了

AbstractXMLParser.class.getClass()

這是抽象類的類,它總是Class而不是你應該只使用getClass()到具體類的類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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