简体   繁体   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

I am trying to implement Lazy Singleton with Generics and Inheritance. 我试图用泛型和继承实现Lazy Singleton。 I have created a abstract super-class and declared a Map which will store all the instances of the child class of this class. 我创建了一个abstract超类,并声明了一个Map,它将存储该类的子类的所有实例。

Here it is: 这里是:

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;
        }
    }
}

And one of the child class is: 其中一个儿童班是:

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

    private ActivityTypeXMLParser() {

    }

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

    }
}

The main method is for testing purpose. main方法是用于测试目的。 But I am getting exception: 但我得到例外:

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)

Now after debugging I found that 现在调试后我发现了

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

is the reason for the exception, because AbstractXMLParser.class.getClass().getGenericSuperclass() is returning class java.lang.Object . 是异常的原因,因为AbstractXMLParser.class.getClass().getGenericSuperclass()返回class java.lang.Object I need to get the Class<T> here. 我需要在这里获得Class<T> How can I extract it in the class AbstractXMLParser and in SingletonHolder of AbstractXMLParser ? 我怎样才能提取它的类AbstractXMLParserSingletonHolderAbstractXMLParser

There are multiple issues with this code: 此代码存在多个问题:

  • static methods are not inherited. static方法不是继承的。 AbstractXMLParser.getInstance() doesn't know that it's invoked in context of ActivityTypeXMLParser when called as ActivityTypeXMLParser.getInstance() . 当调用ActivityTypeXMLParser.getInstance()时, AbstractXMLParser.getInstance()不知道它在ActivityTypeXMLParser上下文中被调用。

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

  • It's not clear why do you need AbstractXMLParser<T> to be generic at all. 目前尚不清楚为什么需要AbstractXMLParser<T>才是通用的。 Note that T s in AbstractXMLParser , SingletonHolder and getInstance() are different type parameters. 请注意, AbstractXMLParserSingletonHoldergetInstance()中的T是不同的类型参数。

You need to pass the class in question to getInstance() implicitly: 您需要隐式地将有问题的类传递给getInstance()

getInstance(ActivityTypeXMLParser.class);

.

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

Here is the complete solution that I have made, would be helpful for someone. 这是我所做的完整解决方案,对某人有帮助。

The abstract super-class : 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);
        }
    }
}

And one of the child class: 其中一个孩子班:

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;
    }
}

You appear to want to get the generic type of the class which is a sub class of the abstract class. 您似乎想要获取类的泛型类型,该类是抽象类的子类。 However you are getting 但是你得到了

AbstractXMLParser.class.getClass()

This is class of the abstract class which is always Class Instead you should use just getClass() to the the class of the concrete class. 这是抽象类的类,它总是Class而不是你应该只使用getClass()到具体类的类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.lang.ClassCastException:无法将java.lang.Class强制转换为java.lang.reflect.ParameterizedType - java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType ClassCastException:java.lang.Class无法强制转换为java.lang.reflect.ParameterizedType - ClassCastException:java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType java.lang.Class无法强制转换为java.lang.reflect.ParameterizedType - java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType 类不能转换为java.lang.reflect.ParameterizedType - Class cannot be cast to java.lang.reflect.ParameterizedType 嵌套类不能转换为java.lang.reflect.ParameterizedType - Nested class cannot be cast to java.lang.reflect.ParameterizedType 测试DAO时出错:sun.reflect.generics.reflectiveObjects.TypeVariableImpl无法强制转换为java.lang.Class - Error testing DAOs: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class class java.lang.Class cannot be cast to class java.lang.reflect.Parameterized - class java.lang.Class cannot be cast to class java.lang.reflect.Parameterized java.lang.Class和泛型 - java.lang.Class and generics 引起:java.lang.ClassCastException:使用Generic Type时,libcore.reflect.ParameterizedTypeImpl无法强制转换为java.lang.Class - Caused by: java.lang.ClassCastException: libcore.reflect.ParameterizedTypeImpl cannot be cast to java.lang.Class when use Generic Type Java:ClassCastException-无法将java.lang.Class强制转换为 - Java: ClassCastException - java.lang.Class cannot be cast to
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM