如何在这里推断generics类型?

public static void main(String[] args) { Map<String, Map<Long, List>> map = getHashMap(); } static  Map getHashMap() { return new HashMap(); } 

我在google guava(作为工厂方法)中看到了类似的代码,用于制作Hashmap的实例而不提及generics类型。我不明白generics是如何通过上述程序推断的。我的意思是函数getHashMap如何理解类型因为我没有将任何类型的信息传递给函数。

getHashMap函数不必推断类型。 在调用站点,Java语言规范要求javac推断类型是一致的( 15.12.2.7基于实际参数推断类型参数 )。

我相信当前的计划(仍然)是JDK7支持钻石操作符,所以这种东西也适用于new ,虽然有一些显然毫无意义的语法。

 Map>> map = new HashMap<>(); ^^diamond 

在字节码级别,该方法将有一个描述符,只是说,有一个名为getHashMap的方法,它不带参数并返回一个Map(没有generics)。

然后当编译器分析行Map>> map = getHashMap(); ,它会说,好吧,我需要一个声明类型为Map>>的变量,但要实际获取我需要调用方法的实例。 此时,编译器的工作是检查方法的返回类型是否与您为其分配结果的变量的声明类型相匹配。 因此它检查StringK匹配,如果Map>与V匹配,那么它认为赋值是类型安全的,并生成基本上使用Map(无generics)变量的字节码。

如果您将声明的方法声明为:

 static  Map getHashMap() { return new HashMap(); } 

在分析赋值时,编译器会看到StringK extends Number不匹配,会抛出编译错误,并且不会为该赋值创建字节码。

 class XX static  T foo(){ return null; } String s = XX.foo(); Integer i = XX.foo(); 

Java推断第一种情况下T是String,第二种情况下是Integer。

“推断”是什么意思? 这意味着Java猜测在两个语句中,程序员最喜欢在第一种情况下需要T == String,对于第二种情况,T == Integer,作为一个好人,Java将这些猜测视为事实,程序员不会必须手动指定Ts

  String s = XX. foo(); Integer i = XX.foo(); 

但实际上,Java 规定返回类型T必须这样确定。

我发现这个东西非常腥,不知道设计背后的原因是什么。 也许,当(if)Java添加可重用类型(即T的真实类在运行时可用)时,设计更有意义:

 class XX static  T foo(){ return new T(); } String s = XX.foo(); Integer i = XX.foo(); 

我仍然不喜欢方法的类型依赖于上下文的事实。