java - 对 Java 泛型的误解

标签 java generics

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

我有一种签名是

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>其中 Umeasure的真正运行时类,你知道 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/

相关文章:

java - 具有固定单元格宽度和居中文本的 itext 表格

java - 如何获取登录用户名?

c# - 没有装箱或类型参数转换

java - 我可以将以下代码转换为使用泛型吗?

java - 如何引用当前类的类型?

java - Java 中的 SuppressWarnings ("unchecked") 是什么?

java - IOS 推送通知 java 服务器端错误 "Received fatal alert: certificate_unknown"

java - 无需行分隔符即可高效加载文本

ios - 如何忽略泛型类型信息并启用属性的协变?

java - 根据通用类型创建对象