我有一个T类型的对象(泛型)
public <T> void method1(T object) {...}我想对该对象使用getClass()方法。
Class<? extends T> clazz = object.getClass();但是编译器显示错误:
Incompatible types.
Found: 'java.lang.Class<capture<? extends java.lang.Object>>'
Required: 'java.lang.Class<? extends T>'如何更正我的代码,使编译器能够编译,clazz对象将具有泛型类型T或<?扩展T>而不进行浇铸?
发布于 2021-08-16 02:12:32
丑陋的演员是唯一的方法:
Class<? extends T> clazz = (Class<? extends T>) object.getClass();..。然后禁用使用@SuppressWarnings执行此操作时收到的警告。
更普遍地说,甚至想要Class对象都是错误的。也许,在你认为自己需要它的原因上,有一个更好的选择。
对于实际类型,代码工作正常(请参见文档,但类型不是:
实际结果类型是Class<?扩展|X|>,其中x_x是对调用getClass的表达式的静态类型的擦除。例如,在此代码片段中不需要强制转换:
在这里,“静态类型的擦除”只是针对您的特定T的T,因此,您可以得到Class<? extends Object>,它只是Class<?>,除非您进行丑陋的强制转换,否则不能将它分配给Class<? extends T>类型的变量。它为什么会这样工作?嗯,是的,斯派克这么说的。我承认我不知道为什么,但事实就是如此。
注意:您也可以添加一个参数:void foo(Class<? extends T> clazz, T value),但是现在您正在通过传递一个看似无用的附加参数来困扰调用方。可能不是个好主意。编译器至少会检查调用者,如果它们传递(例如String.class ),然后将整数作为值传递,则会发出抱怨。
发布于 2021-08-27 16:49:31
添加到另一个答案中,.getClass()返回Class<? extends |X|> (其中|X|是对调用getClass的表达式的静态类型的擦除)的原因是X可能是参数化类型,拥有Class<a parameterized type>或Class<? extends a parameterized type>是不安全的。
例如,以Class<ArrayList<String>>为例。但是实际上只有一个Class实例表示ArrayList --它并不是特定于ArrayList<String>或ArrayList<Integer>等。如果您有一个Class<ArrayList<String>>类型的表达式,您可以调用它并传递任何对象并在没有警告的情况下获得ArrayList<String>,但这是欺骗性的,因为它并没有真正检查对象是否是ArrayList<String> (在运行时无法这样做);它只检查它是一个ArrayList;如果它是一个ArrayList<Integer>,您可能仍然会得到一个令人讨厌的惊喜。类似地,使用Class<ArrayList<String>>,您可以在它上调用.isInstance()并传递一个ArrayList<Integer>并获取true。
对于一个Class<? extends ArrayList<String>>,同样的情况也是如此;也就是说,您可以在它上调用.cast()并得到一个ArrayList<String>,您也可以在它上调用.isInstance(),并得到欺骗性的结果。那些是不安全的。因此,您不应该能够在没有警告的情况下获得Class<? extends ArrayList<String>>类型。因为在您的代码中,T可能是一个参数化类型(编译器必须假设类型变量可以是其范围内的任何类型),所以编译器不能在没有警告的情况下给出一个Class<? extends T>。它必须返回编译时已知的类型才是安全的,语言设计器选择的选项是Class<? extends |T|>,在您的示例中是Class<? extends Object>。
https://stackoverflow.com/questions/68796693
复制相似问题