为什么这段通用代码可以编译?

3

Javac 推断 f() 方法中的 TString。语言规范中的哪些规则导致了这个结论?

<T> T g(){ return null; }

String f()
{
    return g();
}
3个回答

9
我怀疑编译器有效地使用了第15.12.2.8节
如果方法结果出现在将被转换为类型S的赋值转换(§5.2)的上下文中,则让R成为该方法的声明结果类型。
这相当于将返回语句视为将要进行赋值转换。例如,想象一下我们将f()转换为:
String f()
{
    String tmp = g();
    return tmp;
}

现在关于它是否受到赋值转换的影响,第14.17节(返回语句)包含以下内容:

带表达式的返回语句必须包含在声明为返回值的方法声明中(§8.4),否则会出现编译时错误。表达式必须表示某种类型T的变量或值,否则会出现编译时错误。类型T必须可分配(§5.2)到方法的声明结果类型,否则会出现编译时错误。

对5.2的引用是“赋值转换”部分,因此我想这意味着表达式g()受到“赋值转换”的影响,导致第15.12.2.8节的那一部分适用。

0

由于g是一个通用方法,Java会推断出g的类型以匹配f的返回类型。

你可以通过尝试以下三个函数来了解这一点。

class SomeClass{

   <T> T g(){return null;}

   String f() {
      return this.<String>g();
   }

   Integer h() {
      return this.<Integer>g();
   }

   Integer i() {
      return this.<String>g();
   }
}

f和h将编译成功,因为它从返回类型推断类型。i将无法编译,因为类型不匹配。


0

由于g()的泛型返回类型被用作f()的返回类型,并且f()已经被强制类型化为String,因此T被推断为一个字符串。为了使语句有效,T必须是一个字符串,因此就是这样。


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