我的代码中遇到了一个令人困惑的问题。
我有一个签名是
的方法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>
,但我不明白为什么,因为测量对象是T类型,它扩展了Measure。
有没有办法解决这个问题,最重要的是,为什么它不起作用?
谢谢!
编辑:
这是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);
答案 0 :(得分:5)
.getClass()
的类型不是您认为的类型。 .getClass()
返回Class<? extends |X|>
,其中|X|
是要调用的表达式的静态类型的擦除。在这种情况下,measure
具有静态类型T
,其具有擦除Measure
,因此measure.getClass()
具有类型Class<? extends Measure>
,即类型参数是未知的子类型Measure
和.sendNewMeasure(measure.getClass(), measure)
编译器无法保证measure
(类型T
)是此未知类型的实例。
基本上,问题是.getClass()
丢失了类型信息。它的返回类型并不直接与它所调用的东西的类型相关联,因为Java类型系统无法表达&#34;它所调用的事物的真实运行时类型的概念&#34;。但是,直观地说,您知道使用当前签名.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
,所以我们仍然两种类型之间没有联系。我们需要该类型的真实姓名,而不是通配符,以便我们维护此链接。将通配符转换为命名类型的方法是 capture ,这需要将其传递给泛型方法:
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);
}
答案 1 :(得分:3)
来自Java API for
Class<?> getClass()
[...] 实际结果类型为Class<? extends |X|>
其中| X |是擦除调用getClass的表达式的静态类型。
因此measure.getClass()
的结果不是Class<T>
而是Class<? extends T>
你的签名应该是:
public <T extends Measure> void sendNewMeasure(Class<? extends T> type, T measure);