Java泛型方法:从参数类型推断返回类型的上限时出现不一致

时间:2018-03-23 14:58:14

标签: java generics type-inference type-erasure

请考虑以下事项:

class Col<T> { }
class Tag<T> { }
class Foo { }
class Bar { }
class Baz extends Bar { }
class Test {
   static <T, V extends T> Col<V> safe (Tag<T> t) { return null; }
   static <T, V extends T> Col<V> unsafe (T t) { return null; }
}

然后这将产生所需的编译时错误(因为Baz不扩展Foo):

Col<Baz> col = Test.safe (new Tag<Foo> ());

但这不会:

Col<Baz> col = Test.unsafe (new Foo ());

以供参考,这是按预期编译的(因为Baz扩展了Bar):

Col<Baz> col = Test.safe (new Tag<Bar> ());

为什么编译器(Java 8)可以推断并使用T作为'safe'情况下返回类型参数的上限,但不是'不安全'的情况?

我想我理解为什么它在'不安全'的情况下不起作用,因为T被Object删除,但可能有点惊讶它适用于'安全'的情况。至少我发现它不一致。

1 个答案:

答案 0 :(得分:4)

Col<Baz> col = Test.unsafe (new Foo ());
在这种情况下,

Test.unsafe推断TObject;因为所有内容都延伸Object,所以边界得到满足。

Col<Baz> col = Test.safe (new Tag<Foo> ());
在这种情况下,

T无法推断为Object:它是Foo,因为您已经说过它Foo V,没有任何界限。同样,Baz正是Baz。由于Foo不会扩展calendar.month_name[3] ,因此编译错误。