首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >设计模式:惰性单例、泛型和继承:不能将java.lang.Class转换为java.lang.reflect.ParameterizedType

设计模式:惰性单例、泛型和继承:不能将java.lang.Class转换为java.lang.reflect.ParameterizedType
EN

Stack Overflow用户
提问于 2013-01-06 16:44:52
回答 3查看 997关注 0票数 0

我正在尝试使用泛型和继承来实现Lazy Singleton。我已经创建了一个abstract超类,并声明了一个映射,它将存储这个类的子类的所有实例。

这就是它:

代码语言:javascript
运行
复制
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;
        }
    }
}

其中一个子类是:

代码语言:javascript
运行
复制
public class ActivityTypeXMLParser extends AbstractXMLParser<ActivityTypeXMLParser>{
    private ActivityTypesXMLModel activityTypes;

    private ActivityTypeXMLParser() {

    }

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

    }
}

main方法用于测试目的。但是我得到了一个例外:

代码语言:javascript
运行
复制
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)

现在,经过调试,我发现

代码语言:javascript
运行
复制
Class<T> clazz = (Class<T>) ((ParameterizedType) AbstractXMLParser.class.getClass().getGenericSuperclass()).getActualTypeArguments()[0];

是异常的原因,因为AbstractXMLParser.class.getClass().getGenericSuperclass()返回class java.lang.Object。我需要把Class<T>放在这里。如何在AbstractXMLParser类和AbstractXMLParserSingletonHolder中提取它

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-01-06 17:19:25

此代码存在多个问题:

  • static方法不是继承的。AbstractXMLParser.getInstance()不知道当ActivityTypeXMLParser.getInstance().
  • AbstractXMLParser.class.getClass()返回你的类的, not类时,它是在ActivityTypeXMLParser的上下文中被调用的。
  • 不清楚为什么你需要AbstractXMLParser<T>是泛型的。请注意,AbstractXMLParserSingletonHoldergetInstance()中的T是不同的类型参数。

您需要将有问题的类隐式传递给getInstance()

代码语言:javascript
运行
复制
getInstance(ActivityTypeXMLParser.class);

代码语言:javascript
运行
复制
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T extends AbstractXMLParser> T getInstance(Class<T> clazz) 
    throws InstantiationException, 
    ...
}
票数 1
EN

Stack Overflow用户

发布于 2013-01-06 18:59:15

这是我做的完整的解决方案,会对某些人有帮助。

The abstract super-class

代码语言:javascript
运行
复制
@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);
        }
    }
}

和其中一个子类:

代码语言:javascript
运行
复制
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;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2013-01-06 17:40:48

您似乎想要获取类的泛型类型,该类是抽象类的子类。不管你得到了什么

代码语言:javascript
运行
复制
AbstractXMLParser.class.getClass()

这是抽象类的类,它总是Class,而您应该只使用getClass()来表示具体类的类。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14180619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档