[英]Java required type <T> provided <?> generic compilation error
Java 怎么无法解释这段代码:
private <T> Class<T> getClass(T object) {
return object.getClass();
}
我试图想象这一点,当我代替一个例子时
private Class<String> getClass(String s) {
return s.getClass();
}
我得到了同样的错误: required type <String>
provided type <? extends String>
provided type <? extends String>
。 我已经看到通过执行以下操作来解决此错误的代码:
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) object.getClass();
这是什么意思? 我对这个 generics 问题有什么不明白的地方?
getClass
遵循一些有点不寻常的特定规则。 声明的返回类型 Object::getClass 只是Class<?>
,即某种类型的 class 。 但根据文档
实际结果类型是
Class<? extends |X|>
Class<? extends |X|>
其中 |X| 是调用getClass
的表达式的 static 类型的擦除。
您的示例中 T 的擦除只是 Object,所以返回是Class<? extends Object>
Class<? extends Object>
。 一切都扩展了 Object,因此与Class<?>
相同。
当参数为具体类型String时,擦除也为String,结果为Class<? extends String>
Class<? extends String>
。
我猜在幕后发生的事情是编译器有效地“覆盖” Object::getClass 并具有更具体的返回类型。 允许子类返回比其父类更具体的类型,但不能不那么具体。 考虑这个有效的代码:
class Foo {
public Class<? extends List<?>> foo() { return null; }
}
class Bar extends Foo {
@Override
public Class<? extends ArrayList<?>> foo() { return null; }
}
由于这是如何实现的, T obj; obj.getClass();
T obj; obj.getClass();
将返回Class<?>
,而不是您期望的Class<? extends T>
Class<? extends T>
。
在你的情况下,演员是安全的。
由于类型仍在擦除,因此您只有一个Object object
。
Class<?> type = object.getClass();
反过来,可以使用:
private <T> T getObject(Object object, Class<T> type) {
return type.cast(object);
}
上面做了一个动态的运行时转换。 这可能有用:
private final Map<Class<?>, Object> singletonsByType = new HashMap<>();
public <T> void store(Class<T> type, T object) {
singletonsByType.put(type, object);
}
public <S> S lookup(Class<S> type) {
return type.cast(singletonsByType.get(type));
}
你可以像这样解决这个问题:
private <T> Class<T> getClass(T object) {
return (Class<T>)object.getClass();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.