为什么这个通用代码会编译?

时间:2011-02-17 17:50:12

标签: java generics

Javac推断方法T中的Stringf()。语言规范中的哪些规则可以得出结论?

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

String f()
{
    return g();
}

3 个答案:

答案 0 :(得分:9)

我怀疑编译器正在有效地使用section 15.12.2.8

  

如果方法结果发生在将要进行赋值转换(第5.2节)的上下文中,那么让R成为方法的声明结果类型

这是将return语句视为需要进行赋值转换。例如,假设我们将f()转换为:

String f()
{
    String tmp = g();
    return tmp;
}

现在关于 是否需要进行赋值转换,section 14.17(return语句)包含:

  

带有Expression的return语句必须包含在声明为返回值(第8.4节)或发生编译时错误的方法声明中。 Expression必须表示某种类型T的变量或值,否则会发生编译时错误。类型T必须是可分配的(第5.2节)到方法的声明结果类型,否则会发生编译时错误。

对5.2的引用是“赋值转换”部分,所以我猜这意味着表达式g() “受赋值转换”,导致第15.12节的那一部分。 2.8适用。

答案 1 :(得分:0)

T被推断为一个String,因为g()的泛型返回类型被用作f()的返回类型,它强烈地键入String。为了使语句有效,T必须是String,所以它是。

答案 2 :(得分: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将编译正常,因为它从返回类型推断出类型。我不会编译,因为类型不匹配。