我在我的代码中遇到了一个令人困惑的问题。
我有一种方法,其签名是
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:这是 find 方法签名,我无法更改:
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
(of type) o这种未知类型的实例。
基本上,问题在于 T
丢失了类型信息。它的返回类型与它被调用的事物的类型没有直接联系,因为 Java 类型系统无法表达“它被调用的事物的真正运行时类型”的概念。但是,直观上,你知道调用当前签名为 .getClass()
的方法是类型安全的,因为 .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
,所以我们仍然没有这两种类型之间的链接。我们需要类型的真实名称,而不是通配符,以便我们维护此链接。将通配符转换为命名类型的方法是捕获,这需要将其传递到泛型方法中:
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/