首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java :不兼容类型: capture<?扩展Object>和<?扩展T>

Java :不兼容类型: capture<?扩展Object>和<?扩展T>
EN

Stack Overflow用户
提问于 2021-08-16 02:04:34
回答 2查看 1.3K关注 0票数 1

我有一个T类型的对象(泛型)

代码语言:javascript
复制
public <T> void method1(T object) {...}

我想对该对象使用getClass()方法。

代码语言:javascript
复制
Class<? extends T> clazz = object.getClass();

但是编译器显示错误:

代码语言:javascript
复制
Incompatible types.
Found:    'java.lang.Class<capture<? extends java.lang.Object>>'
Required: 'java.lang.Class<? extends T>'

如何更正我的代码,使编译器能够编译,clazz对象将具有泛型类型T或<?扩展T>而不进行浇铸?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-08-16 02:12:32

丑陋的演员是唯一的方法:

代码语言:javascript
复制
Class<? extends T> clazz = (Class<? extends T>) object.getClass();

..。然后禁用使用@SuppressWarnings执行此操作时收到的警告。

更普遍地说,甚至想要Class对象都是错误的。也许,在你认为自己需要它的原因上,有一个更好的选择。

对于实际类型,代码工作正常(请参见文档,但类型不是:

实际结果类型是Class<?扩展|X|>,其中x_x是对调用getClass的表达式的静态类型的擦除。例如,在此代码片段中不需要强制转换:

在这里,“静态类型的擦除”只是针对您的特定TT,因此,您可以得到Class<? extends Object>,它只是Class<?>,除非您进行丑陋的强制转换,否则不能将它分配给Class<? extends T>类型的变量。它为什么会这样工作?嗯,是的,斯派克这么说的。我承认我不知道为什么,但事实就是如此。

注意:您也可以添加一个参数:void foo(Class<? extends T> clazz, T value),但是现在您正在通过传递一个看似无用的附加参数来困扰调用方。可能不是个好主意。编译器至少会检查调用者,如果它们传递(例如String.class ),然后将整数作为值传递,则会发出抱怨。

票数 3
EN

Stack Overflow用户

发布于 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>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68796693

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档