假设有一个类A:class A<T> {
...
}我在实例化这个模板类的时候,想利用反射填入一个动态的类型进去,类似这样:A<?> a = new A<Class.forName("B")>();但是这样是不行的,语法错误,不知有何办法?考虑过构造一个相应Class对象,然后使用newInstance方法,但是Class类没有构造方法,只能用forName创建实例,似乎构造不出带参数的类型来,请问如何解决?
...
}我在实例化这个模板类的时候,想利用反射填入一个动态的类型进去,类似这样:A<?> a = new A<Class.forName("B")>();但是这样是不行的,语法错误,不知有何办法?考虑过构造一个相应Class对象,然后使用newInstance方法,但是Class类没有构造方法,只能用forName创建实例,似乎构造不出带参数的类型来,请问如何解决?
去看看java源码吧,看看人家怎么写的
List<T>是模板类本身的语法,在实例化的时候要指明T的具体类型,然后在静态编译的时候通过替换实现的。而我要求的是填入动态参数,也就是说T的类型是在程序运行的时候确定的,按理说Java对动态性的支持还不错,应该可以实现的,只是不知道怎么做。
所以在运行时修改泛型是不可能的但是,不是很明白你的需求,如果只是传递一个动态对象的话,以Object为参数传递不就行了吗,为何要用泛型来做这个事情
Constructor c = clazz.getConstructor(new Class[]{});
c.newInstance(new Object[]{});class和object的数组要对应
class A {
Class<?> type; A(Class<?> type) {
this.type = type;
}
//doSomething
}
我认为用Object太泛了,有时候需要在特定的环境中做一个限制,比如说List<T>,在一次调用中,我传入了一个Integer作为参数,这样在这次调用中,这个List只能插入Integer的对象,下一次如果我传入一个Double,则在整个调用中只能插入Double;而如果以Object作为对象,则在一次调用中可能既可以插入Integer,又可以插入Double,没有具体的约束,也就违背了Java给泛型加参数的本意。
你这个是创建了一个带参数的Constructor对象,而我的意思是,不能创建一个带参数的模板类的Class对象,即你这里的clazz这个对象。
public static <T> T creat(Class<T> cls) {
try {
return cls.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
} public static void main(String[] args) {
Date d = ObjectCreator.creat(Date.class);
System.out.println(d);
}
}
这个似乎无法解决我的问题,我的需求是创建一个模板类的对象,即在你给你例子中,要将Date替换为一个类似List<X>的东西,这个X还要是动态可变的。
综合楼上几位的观点,我也渐渐接受了Java无法实现这个功能的现实……
泛型的检查仅仅处于编译期,也就是说,你在IDE里看到的那些List<Integer>中不能存放DOUBLE类型的错误提示,都是IDE的预编译错误提示
在程序运行期间,List不会关心你到底存了什么对象进去
至于你说的泛型的动态存储,有一个折中的办法,看代码:class MyType<T> {
// 自定义泛型类
}
public <X> MyType<X> getMyTypeInstance(Class<X> clazz) {
return new MyType<X>();
}public void test() {
MyType<Integer> type = getMyTypeInstance(Integer.class);
}
因为泛型不能通过反射获取,你可以制作一些工厂来获取相关的对象