我的代码中遇到了一个令人困惑的问题。
我有一种签名是
public <T extends Measure> void sendNewMeasure(Class<T> type, T measure);
在另一个类中,我有这个方法,它调用前一个方法:
public <T extends Measure> void onNewMeasure(NewMeasureEvent<T> event) {
T measure = event.getMeasure();
APIInterface.getInstance().sendNewMeasure(measure.getClass(), measure);
}
我得到的错误是 Wrong argument type, found 'T', required <? extends com.blablabla.Measure>
但我不明白为什么,因为度量对象是扩展 Measure 的 T 类型。
有什么方法可以解决这个问题,最重要的是,为什么它不起作用?
谢谢!
编辑:
这是 sendNewMeasure 方法的实现:
public <T extends Measure> void sendNewMeasure(Class<T> type, T measure) {
String measureType = measure.getJSONMeasureTypeName();
List<T> measures = T.find(type, measure.timestamp, true, false);
measures.add(measure);
sendMeasures(siteId, sensorId, measureType, measures);
}
编辑 2:这是查找方法签名,我无法更改的签名:
public static <T> List<T> find(Class<T> type, int timestamp, boolean includeStart, boolean inclueEnd);
最佳答案
.getClass()
的类型不是你想的那样。 .getClass()
返回 Class<? extends |X|>
, 其中|X|
是删除它所调用的表达式的静态类型。在这种情况下,measure
有静态类型 T
, 其中有删除 Measure
, 所以 measure.getClass()
类型为 Class<? extends Measure>
,即类型参数是 Measure
的未知子类型, 和 .sendNewMeasure(measure.getClass(), measure)
编译器无法保证 measure
(类型 T
)是此未知类型的一个实例。
基本上,问题是 .getClass()
丢失类型信息。它的返回类型没有直接链接到它被调用的事物的类型,因为 Java 类型系统无法表达“它被调用的事物的真实运行时类型”的概念。但是,直觉上,您知道调用具有当前签名的方法 .sendNewMeasure(measure.getClass(), measure)
是类型安全的,因为 measure.getClass()
的类型真的应该是 Class<U>
其中 U
是measure
的真正运行时类,你知道 measure
显然是相同类型的实例 U
,所以存在一些类型参数,这个 U
(不一定与 T
相同)为此调用 .sendNewMeasure()
类型检查,但问题是如何在不使用未经检查的操作的情况下说服编译器。
问题是 measure.getClass()
返回的类型没有充分链接到 measure
的类型.重新链接它们的一种方法是使用类将对象转换为其类型(这将始终成功),使用类的方法 .cast()
.但是用 Class<? extends Measure>
类型的表达式来做这件事并没有帮助。 ,因为 .cast()
的结果是? extends Measure
这只会降级为 Measure
,所以我们仍然没有这两种类型之间的联系。我们需要类型的真实名称,而不是通配符,以便我们维护此链接。将通配符转换为命名类型的方法是捕获,这需要将其传递给泛型方法:
public <T extends Measure> void onNewMeasure(NewMeasureEvent<T> event) {
T measure = event.getMeasure();
helper(measure.getClass(), measure);
}
private <U extends Measure> void helper(Class<U> clazz, Measure measure) {
U castedMeasure = clazz.cast(measure);
APIInterface.getInstance().sendNewMeasure(clazz, castedMeasure);
}
关于java - 对 Java 泛型的误解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34526983/