具有类对象作为泛型类型的Java泛型

时间:2018-08-10 21:21:09

标签: java generics

我想为使用泛型定义的类创建Java对象。 具体来说,我想创建一个在运行时确定的类的对象列表。

我想要类似的东西

Class clazz = Class.forName("MyClass");
List<clazz> myList = new ArrayList<>(); // This isn't allowed

定义一个对象数组将允许我存储MyClass类型的对象列表,但这将导致每次从列表中获取对象时都强制转换对象,我想避免这种情况。

有没有一种方法可以使用Java来实现类似于上面的代码。

4 个答案:

答案 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>

您可以执行以下操作之一:

  1. 如果您对这些类有共同的基础(例如JDBC Driver),请使用接口。
  2. 例如,使用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做任何事情。而且,您必须在使用它的每个方法上声明一个类型参数。