我在我的代码中遇到了一个令人困惑的问题。

我有一种方法,其签名是

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/

10-12 05:48