Java泛型返回类型方法派生成对象返回类型

3

我遇到了这个奇怪的问题。

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(),我会得到一个编译错误:

不兼容的类型:无法将Object转换为C,其中C是一个类型变量。

但是如果m作为声明的类型化对象,则编译错误消失了。
我无法理解为什么参数会对编译器确定返回类型产生影响。对于Bar类示例中的通用类型T,编译器在任何情况下都不应认为它是Object类型。有人能指出我错在哪里吗?谢谢。

我似乎无法复现这个问题。 - Sweeper
@JacobG。嗨,Jacob,这就是我不理解的地方,为什么类型抹除认为它是对象类型而不是泛型类型C? - woodybird
有趣的是,问题并不是由类型推断引起的,因为即使使用 return bar.<C>barMethod(m); 显式地将 T 设置为 C,问题仍然存在。 - Marco
2个回答

0
Map m = new HashMap<>();
return bar.barMethod(m); //error

错误是由于barMethod(Map<String, String> m)需要一个特定的Map<String, String>而引发的。您可以采取一些措施来消除编译错误。
  • barMethod参数更改为原始类型。

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

    或者

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

    return (C) bar.barMethod(m);
    

    或者

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

    public Object fooMethod()
    

错误不在于参数类型,而是在于此方法的返回类型无法转换为我的情况下的通用类型C。 - woodybird

0

我在规范中找不到任何来源,但基本上,因为您在通用类型Map<String,String>的位置使用了原始类型Map,Java将所有通用参数(而不仅仅是Map)转换为类型擦除的Object。 方法签名有效地变成:

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

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

即使使用return bar.<C>barMethod(m);将T明确设置为C,错误仍然存在。你如何解释这个问题? - Marco
@Marco 就像我说的,你要么使用完全通用的版本,要么使用完全原始的版本。Java 忽略了 <C>(在任何情况下都是多余的)。 - Michael
为什么在这种情况下,泛型类型<C>没有被类型擦除为Object? - woodybird
这是一个不同的方法调用。 - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接