如何在没有编译器警告的情况下将java.lang.Class类型的变量初始化为具有泛型的集合?
我需要初始化类型为如何在没有编译器警告的情况下将java.lang.Class类型的变量初始化为具有泛型的集合?,java,generics,Java,Generics,我需要初始化类型为Class 当我使用Set.class时,它返回class Class clazz=Set.Class; 当我尝试 Class<Set<String>> clazz = Set<String>.class; Class clazz=Set.Class; 我有一个编译错误。首先,您需要了解,在运行时,只有一个类对象表示集接口。对于Set、Set等,没有单独的Class对象。因此Class类型的变量在运行时最多只能指向这个Set类对象,问题
Class
当我使用Set.class时,它返回class
Class clazz=Set.Class;
当我尝试
Class<Set<String>> clazz = Set<String>.class;
Class clazz=Set.Class;
我有一个编译错误。首先,您需要了解,在运行时,只有一个
类
对象表示集
接口。对于Set
、Set
等,没有单独的Class
对象。因此Class
类型的变量在运行时最多只能指向这个Set
类对象,问题是这样做有意义吗
让我们考虑使用类型变量<代码>类< /代码> >
。- 您可以调用它的
方法。通常,如果您有一个.cast()
,类clazz
返回typeclazz.cast(x)
,它在运行时的作用是检查传递的对象是否是该类的实例,如果不是,则抛出异常;这就是为什么它可以安全地返回类型T
。但是,如果变量指向表示T
接口的集
对象,则其类
只能检查该对象是否是.cast()
的实例,而不是集
的实例(无论如何,这是不可能的,因为对象在运行时不知道它们的泛型类型参数;如果您执行强制转换集
,它将给出一个未经检查的强制转换警告;因此,如果您能够在没有警告的情况下通过执行(Set)x
来“绕过”警告,则没有意义),因此它无法“安全地”返回类型Set.class.cast(x)
Set
- 您可以调用它的
方法。通常,如果您有.isInstance()
,类clazz
根据传递的对象是否是clazz.isInstance(x)
的实例返回true或false。但只需使用T
,无法在运行时检查对象的泛型类型参数,因此调用.cast()
类的
方法可能无法给出“正确”的答案.isInstance()
- 您可以通过调用
方法或获取构造函数并使用构造函数的.newInstance()
使用无参数构造函数获取.newInstance()来创建新实例<代码> >方法。在这种情况下,<代码> SET>代码>是一个接口,不能被实例化;让我们来考虑说,<代码>哈什集。用<代码>类< /C> >,可以调用<代码> .NeWistShans.
。在这种情况下是安全的,因为HashSet
和new HashSet()
在运行时。但是,如果您得到一个带有参数的构造函数,那么如果在参数中使用类型new HashSet()之间没有区别
,则可能是不安全的,因为它无法检查传递的参数是否与这些类型匹配(因为在运行时它不知道T
)T
如您所见,<代码>类< /代码>不能安全地履行<代码>类< /代码>类的某些功能。因此,在没有警告的情况下,您不应该能够获得<代码>类< /代码>。如果您确信用例是安全的,请考虑<代码>类< <代码>对象,表示“代码> SET >作为
Class
,然后您可以通过执行(Class)Set.Class
,手动强制它,但您将得到一条警告,这意味着您将负责确保它的安全。请参阅由于类型擦除(类型参数由编译器删除);以下情况很好:Class clazz=(Class)Set.class;
@Daniele,感谢您提供的解决方案。它可以工作,但会产生编译器警告。我正在尝试在没有警告的情况下找到解决方案。将对我的问题进行澄清。您可以安全地添加@SuppressWarnings({“unchecked”,“rawtypes”})
。也许你可以看看这个问题:@SergeiTarasov:我看不到一个优雅的方法来抑制取消选中的类型。如果集合的初始化是由API的客户端完成的,也许你应该在你的端上添加一个额外的实现,它将在你的端上抑制类型转换,而不是client结束。。。。。
Class<Set<String>> clazz = Set<String>.class;