[英]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
? 我怎样才能提取它的类
AbstractXMLParser
和SingletonHolder
的AbstractXMLParser
?
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. 请注意,
AbstractXMLParser
, SingletonHolder
和getInstance()
中的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.