【问题标题】:Java Generic return type method derived to be object return typeJava Generic 返回类型方法派生为对象返回类型
【发布时间】:2018-10-19 03:44:46
【问题描述】:

我遇到了这个有线问题。

class Foo<R, C> {

    public C fooMethod() {
        Bar bar = new Bar();
        Map<String, String> m = new HashMap<>();
        return bar.barMethod(m);
    }
}

class Bar {
    public <T> T barMethod(Map<String, String> m) {
        Object barObj = null;
        ...
        return (T) barObj;
    }
}

如果我将 m 声明为原始类型 Map m = new Map(),则会出现编译错误:

不兼容的类型:对象不能转换为 C,其中 C 是 类型变量。

但如果m 是上面声明的类型化对象,那么编译错误就消失了。

我无法弄清楚为什么参数会改变编译器来确定返回类型是什么。对我来说,编译器在任何情况下都不应该认为 Bar 类示例中的泛型类型 T 是 Object 类型。有人能指出我错在哪里吗? 提前致谢。

【问题讨论】:

  • 我似乎无法重现这个。
  • @JacobG。嗨 Jacob,这就是我不明白的地方,为什么类型擦除认为它是对象类型而不是泛型 C 类型?
  • 有趣的是,问题不在于类型推断,因为即使使用return bar.&lt;C&gt;barMethod(m); 将 T 显式设置为 C 也是如此。

标签: java generics type-erasure


【解决方案1】:
Map m = new HashMap<>();
return bar.barMethod(m); //error

抛出错误是因为barMethod(Map&lt;String, String&gt; m) 特别需要Map&lt;String, String&gt;。您可以做一些事情来消除编译错误。

  • barMethod 参数更改为原始类型。

    public <T> T barMethod(Map m) {...}
    

  • 在方法fooMethod中将返回值转换为C

    return (C) bar.barMethod(m);
    

  • 将方法fooMethod的返回类型改为Object

    public Object fooMethod()
    

【讨论】:

  • 错误与参数类型无关,在我的情况下,此方法的返回类型不能转换为泛型 C
【解决方案2】:

我在规范中找不到任何来源,但基本上,因为您使用原始类型 Map 代替泛型 Map&lt;String, String&gt;,Java 转换 all 泛型参数(不是只是Map) 到类型擦除的Object。方法签名有效地变成:

public Object barMethod(Map<Object, Object> m)

因为barMethod 返回Object,而Object 不一定是C(由fooMethod 返回),所以类型不兼容。这就是为什么这会导致编译器错误。

【讨论】:

  • 即使使用return bar.&lt;C&gt;barMethod(m); 将 T 显式设置为 C,错误仍然存​​在,您如何解释?
  • @Marco 就像我说的,你要么使用完全通用的版本,要么使用完全原始的版本。 Java 忽略了&lt;C&gt;(在任何一种情况下都是多余的)
  • 在这种情况下,为什么泛型类型 没有被类型擦除为 Object?
  • 这是一个不同的方法调用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
  • 1970-01-01
  • 2018-10-10
  • 2020-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多