我想为使用泛型定义的类创建Java对象。 具体来说,我想创建一个在运行时确定的类的对象列表。
我想要类似的东西
Class clazz = Class.forName("MyClass");
List<clazz> myList = new ArrayList<>(); // This isn't allowed
定义一个对象数组将允许我存储MyClass类型的对象列表,但这将导致每次从列表中获取对象时都强制转换对象,我想避免这种情况。
有没有一种方法可以使用Java来实现类似于上面的代码。
答案 0 :(得分:1)
好吧,由于您知道该课程,因此您可以(带有警告)强制转换List
本身;但是您仍然需要知道类名并对其进行一些检查,例如:
if(clazz.getName().equals("java.lang.String")) {
// warning here
yourList = (List<String>) yourList;
}
答案 1 :(得分:0)
不,您不能。 Java中的泛型只是一种编译时类型检查机制。如果您直到运行时才知道类型,那么很显然,它不能用于编译时类型检查。编译器无法在编译时确定允许您放入或退出List<clazz>
的类型,因此它仅比原始类型List
有意义。
答案 2 :(得分:0)
据我所知,您想知道编译器是否有可能知道运行时类型,而运行时类型仅限于编译类型。
不能。而且您的假设也是错误的:
定义一个对象数组将允许我存储MyClass的列表 键入对象,但这将导致每次铸造对象 该对象是从列表中提取的,我想避免这种情况 场景。
在Java中,泛型不会删除类型转换:它仍然以类型擦除和(隐藏)类型转换的形式存在。当您执行List<String>
时,仅要求编译器隐藏诸如T get(int)
之类的操作中的强制类型转换:将强制转换为String
。
如果您想使用编译时间信息,那将意味着您已经/知道在编译时可用的类型MyClass
,并且您不会使用Class::forName
而是MyClass.class
将会返回Class<MyClass>
。
您可以执行以下操作之一:
Driver
),请使用接口。Class::isAssignableFrom
将原始列表转换为已知类型。答案 3 :(得分:0)
有一个小技巧可用于处理特定的未知类型:声明仅用于未知类型的类型参数:
public <T> void worksWithSomeUnknownClass() throws ReflectiveOperationException {
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) Class.forName("MyClass");
T obj = clazz.getConstructor().newInstance();
List<T> myList = new ArrayList<>();
myList.add(obj);
}
但是,此解决方案非常有限。它可以确保您不会将其与其他未知类型或Object
混在一起,但是您不能真正地{em>做使用T
做任何事情。而且,您必须在使用它的每个方法上声明一个类型参数。