泛型类型推断失败?

pol*_*nts 8 java generics type-inference

例A

研究以下片段:

public class ExampleA {
   static class Pair<F,S> { }

   static <F,S> Pair<F,S> anyPair() { return null; }

   static <F,S> void process(Pair<F,S> p1, Pair<F,S> p2) { return; }

   public static void main(String[] args) {
      Pair<String,Integer> p = anyPair();

      process(p, anyPair()); // doesn't compile
   }
}
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么类型推断适用于局部变量的赋值p但不适用于第二个实际参数process吗?


例B

这可能更容易理解:

public class ExampleB {     
   public static <E> void process(Set<E> s1, Set<E> s2) { return; }

   public static void main(String[] args) {
      process(new HashSet<String>(), Collections.emptySet()); // doesn't compile
   }
}
Run Code Online (Sandbox Code Playgroud)

同样的问题:为什么不编译?

我希望这Collections.emptySet()适用于任何参数化Set类型.

Ala*_*nse 8

您的第二次调用anyPair()无法确定其类型,因此默认为<Object, Object>.

编译器正在分解process(p, anyPair());它们并分别处理它们.当它这样做时,它需要首先处理参数以确定它们的类型,然后可以在处理时使用它们process.

当它进行处理时anyPair(),没有可用于该片段的类型信息,因为它不知道它是process那一点的一部分.它默认为<Object, Object>,然后在查看时导致类型不匹配process.

你的第二个例子也发生了同样的事情. Collections.emptySet()需要自己处理,但无法确定所需的类型.

有两种方法可以解决这个问题:

第一种方法是为编译器提供类型推断所需的信息,方法与第一次调用时相同,方法anyPair()是将其存储在具有正确类型的临时变量中.

第二个(感谢@BalusC)就是用ExampleA.<String, Integer>anyPair().此语法显式设置所需的类型,而不必超出调用范围.

  • 第二种方式:将其传递为`GenericsQ.<String,Integer> anyPair()`. (5认同)
  • 变量赋值的工作原理是您已指定变量的类型.`Pair <String,Integer> p = anyPair();`可以查看它的分配内容并从中推断出类型.`process(p,anyPair());`在确定每个参数的类型以确定要使用的签名之前,不能查看`process`.您可以使用`static <F,S> void进程(Pair <F,S> p1,Object p2)`方法,因此编译器需要首先评估参数.这意味着它无法从方法签名中获取任何信息,包括类型推断. (2认同)