设计模式:惰性单例、泛型和继承:java.lang.Class不能转换为java.lang.reflect.ParameterizedType
我试图用泛型和继承实现懒惰的单例。我创建了一个设计模式:惰性单例、泛型和继承:java.lang.Class不能转换为java.lang.reflect.ParameterizedType,java,generics,inheritance,singleton,lazy-evaluation,Java,Generics,Inheritance,Singleton,Lazy Evaluation,我试图用泛型和继承实现懒惰的单例。我创建了一个abstractsuper类,并声明了一个映射,它将存储这个类的子类的所有实例 这是: public abstract class AbstractXMLParser<T> { @SuppressWarnings("rawtypes") private static final Map<Class<? extends AbstractXMLParser>, AbstractXMLParser> IN
abstract
super类,并声明了一个映射,它将存储这个类的子类的所有实例
这是:
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;
}
}
}
现在调试后我发现
Class<T> clazz = (Class<T>) ((ParameterizedType) AbstractXMLParser.class.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Class clazz=(Class)((ParameterizedType)AbstractXMLParser.Class.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
是异常的原因,因为
AbstractXMLParser.class.getClass().getGenericSuperclass()
正在返回class java.lang.Object
。我需要在这里获取类。如何在类AbstractXMLParser
和AbstractXMLParser
的SingletonHolder
中提取它?此代码存在多个问题:
静态
方法不会被继承AbstractXMLParser.getInstance()
不知道它在调用为ActivityTypeXMLParser.getInstance()时在ActivityTypeXMLParser
的上下文中被调用
AbstractXMLParser.class.getClass()
返回类的class',而不是类的class'
- 不清楚为什么需要
AbstractXMLParser
作为泛型。请注意,AbstractXMLParser
中的T
s、SingletonHolder
和getInstance()
是不同的类型参数
您需要隐式地将有问题的类传递给getInstance()
:
getInstance(ActivityTypeXMLParser.class);
@SuppressWarnings({“unchecked”,“rawtypes”})
公共静态getInstance(类clazz)
抛出实例化异常,
...
}
您似乎想要获取类的泛型类型,它是抽象类的子类。无论你得到什么
AbstractXMLParser.class.getClass()
这是抽象类的类,它始终是class
,而您应该只使用getClass()
来定义具体类的类。以下是我提出的完整解决方案,对某些人可能会有所帮助
抽象超类
:
@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);
}
}
}
@SuppressWarnings({“all”})
公共抽象类AbstractXMLParser{
私有静态最终映射实例=new HashMap();
公共抽象XmlParser(){
}
私有静态类SingletonHolder{
私有静态T getInstance(类clazz)抛出实例化异常、IllegalAccessException、NoSuchMethodException、SecurityException、IllegalArgumentException、InvocationTargetException{
构造函数=(构造函数)clazz.getDeclaredConstructors()[0];
constructor.setAccessible(true);
返回构造函数.newInstance(null);
}
}
受保护的静态T getInstance(类clazz)抛出实例化异常、IllegalAccessException、NoSuchMethodException、SecurityException、IllegalArgumentException、InvocationTargetException{
if(实例.containsKey(clazz)){
return(T)INSTANCES.get(clazz);
}否则{
T instance=SingletonHolder.getInstance(clazz);
实例.put(clazz,instance);
返回实例;
}
}
受保护的静态void实例(类clazz,T实例){
如果(!INSTANCES.containsKey(clazz)){
实例.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;
}
}
公共类ActivityTypeXMLParser扩展了AbstractXMLParser{
私有ActivityTypeXMLParser(){
}
公共静态活动类型XmlParser getInstance(){
ActivityTypeXMLParser ActivityTypeXMLParser=null;
试一试{
activityTypeXMLParser=getInstance(activityTypeXMLParser.class);
}捕获(异常){
}
if(activityTypeXMLParser==null){
activityTypeXMLParser=新activityTypeXMLParser();
putInstance(ActivityTypeXMLParser.class,ActivityTypeXMLParser);
}
返回activityTypeXMLParser;
}
}
感谢您的回复。但是现在我得到另一个错误java.lang.IllegalAccessException for clazz.newInstance()。因为ActivityTypeXMLParser具有私有构造函数。如何克服这个问题?如果您确实需要使用反射访问private
构造函数,请使用setAccessible(true)
。
AbstractXMLParser.class.getClass()
@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;
}
}