Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
类对象作为泛型类型的Java泛型_Java_Generics - Fatal编程技术网

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

类对象作为泛型类型的Java泛型,java,generics,Java,Generics,我想为使用泛型定义的类创建一个Java对象。 具体来说,我想创建一个在运行时确定的类对象列表 我想要像这样的东西 Class clazz = Class.forName("MyClass"); List<clazz> myList = new ArrayList<>(); // This isn't allowed Class clazz=Class.forName(“MyClass”); List myList=new ArrayList();//这是不允许的 定义

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

我想要像这样的东西

Class clazz = Class.forName("MyClass");
List<clazz> myList = new ArrayList<>(); // This isn't allowed
Class clazz=Class.forName(“MyClass”);
List myList=new ArrayList();//这是不允许的

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

有没有一种方法可以使用java实现类似上述代码的功能。

好吧,既然您知道该类,您可以(通过警告)强制转换
列表本身;但您仍然需要知道类名和一些检查,例如:

if(clazz.getName().equals("java.lang.String")) {
     // warning here
     yourList = (List<String>) yourList; 
}
if(clazz.getName().equals(“java.lang.String”)){
//警告这里
yourList=(List)yourList;
}

不,你不能。Java中的泛型只是一种编译时类型检查机制。如果直到运行时才知道类型,那么显然,它不能用于编译时类型检查。编译器无法在编译时确定允许您在
列表
中输入或输出的类型,因此它的意义并不比原始类型
列表
更重要。我理解您的问题,您想知道编译器是否有可能知道运行时类型,而它仅限于编译类型

你不能。你的假设也是错误的:

定义对象数组将允许我存储MyClass的列表
键入对象,但这将导致每次都强制转换对象 该对象是从列表中提取的,我希望避免这种情况 情景

在Java中,泛型不会删除强制转换:它仍然以类型擦除和(隐藏)强制转换的形式存在。当您执行
列表
时,您只需要求编译器隐藏强制转换操作,例如
T get(int)
:将强制转换为
字符串

如果您想使用编译时信息,那么这意味着您已经拥有/知道编译时可用的类型
MyClass
,并且您不会使用
Class::forName
,而是使用
MyClass.Class
,它将返回一个
Class

您可以做的是:

  • 如果这些类(如JDBC
    Driver
    )有共同点,请使用接口
  • 将原始列表强制转换为已知类型,例如使用
    Class::isAssignableFrom

  • 有一个小技巧可用于处理特定的未知类型:声明一个仅用于未知类型的类型参数:

    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);
    }
    
    public void worksWithSomeUnknownClass()引发ReflectiveOperationException{
    @抑制警告(“未选中”)
    Class clazz=(Class)Class.forName(“MyClass”);
    T obj=clazz.getConstructor().newInstance();
    List myList=new ArrayList();
    myList.add(obj);
    }
    

    不过,这个解决方案非常有限。它确保您不会将它与其他未知类型或
    对象混为一谈,但您无法真正使用
    t
    执行任何操作。您必须在每个使用类型参数的方法上声明一个类型参数。

    “但这会导致每次从列表中提取对象时都强制转换对象,我希望避免这种情况。”除了在列表中执行不安全的强制转换外,您无法避免每次都强制转换对象,这不是不合理的。@LouisWasserman但我们如何强制转换到列表由于java不允许这种结构,用反射强制转换单个对象很简单,但是我们可以使用相同的语法强制转换泛型类吗?这是不可能的,因为泛型类型是在编译时解析的,所以在运行时泛型类型基本上不存在。声明后,您希望如何使用列表?。不管怎样,取决于你如何解决它,铸造不应该被关注。你不会。写
    列表
    ,不带泛型。如果你有一个
    ,你可以将它转换成
    列表
    @LouisWasserman我更喜欢
    列表
    ,而不是原始列表。少一个警告。类名是在运行时确定的,它可以是多种类,为解决方案编写这种逻辑是不可能的。@AmanJ您的类可以扩展一个公共接口,以便您可以强制转换到
    列表
    ?否则,铸造每个元素将是唯一的解决方案