我需要初始化Class<Set<String>>
类型的变量
当我使用Set.class时,它返回变量Class<Set>
Class<Set> clazz = Set.class;
当我尝试
Class<Set<String>> clazz = Set<String>.class;
我有一个编译错误。
答案 0 :(得分:2)
首先,您需要了解,在运行时,只有一个Class
对象代表Set
接口。 Class
,Set<String>
等没有单独的Set<Integer>
对象。因此,类型Class<Set<String>>
的变量在运行时可以执行的大多数操作都指向该{{1 }}类对象,问题是这样做是否有意义?
让我们考虑一下如何使用类型为Set
的变量。
Class<Set<String>>
方法。通常,如果您有.cast()
,则Class<T> clazz
返回类型clazz.cast(x)
,并且它在运行时的作用是检查所传递的对象是否是该类的实例,如果不是,则返回引发异常;这就是为什么安全返回类型T
的原因。但是,如果您的变量指向代表T
接口的Class
对象,则其Set
只能检查该对象是.cast()
的实例,而不是它是Set
的实例(无论如何,这是不可能的,因为对象在运行时不知道其泛型类型参数;如果您进行了强制转换Set<String>
,它将给出未经检查的强制转换警告;因此它将如果您能够通过执行(Set<String>)x
而没有警告而“绕过”警告,则没有任何意义),因此它不能“安全地”返回类型Set<String>.class.cast(x)
。Set<String>
方法。通常,如果您有.isInstance()
,则Class<T> clazz
返回true或false取决于传递的对象是否是clazz.isInstance(x)
的实例。但是仅使用T
,就不可能在运行时检查对象的泛型类型参数,因此调用.cast()
的{{1}}方法可能无法给出“正确”的答案。 Class<Set<String>>
方法或通过获取构造函数并使用构造函数的.isInstance()
方法来创建新实例。好吧,在这种情况下,.newInstance()
是一个接口,无法实例化;让我们考虑说.newInstance()
。使用Set
,您可以使用无参数构造函数来调用HashSet
以获取Class<HashSet<String>>
。在这种情况下,这是安全的,因为在运行时.newInstance()
与HashSet<String>
和new HashSet()
之间没有区别。但是,如果您获得带有参数的构造函数,则在参数中使用类型new HashSet<String>()
可能是不安全的,因为它无法检查传递的参数是否与这些类型匹配(因为它不能在运行时不知道new HashSet<Integer>()
。如您所见,T
无法安全地履行T
类的某些功能合同。因此,如果没有警告,您将无法获得Class<Set<String>>
。如果确定使用案例安全,可以将代表Class
的{{1}}对象视为Class<Set<String>>
,则可以通过执行Class
来手动强制它,但是您将收到警告,表示您有责任确保它的安全。