该 getHashMap 函数不必推断类型。在Java语言规范要求javac推断类型一致的调用站点( 15.12.2.7根据实际参数推断类型参数 )。
getHashMap
我相信目前的计划(仍然)是JDK7支持钻石操作员,所以这种事情会起作用 new 虽然有一点显然毫无意义的语法。
new
Map<String, Map<Long, List<String>>> map = new HashMap<>(); ^^diamond
在字节码级别,该方法将有一个描述符,只是说,有一个名为getHashMap的方法,它不带参数并返回一个Map(没有泛型)。
然后当编译器分析该行时 Map<String, Map<Long, List<String>>> map = getHashMap(); ,它会说,好吧,我需要一个声明类型为的变量 Map<String, Map<Long, List<String>>> ,但要实际获取我需要调用方法的实例。此时,编译器的工作是检查方法的返回类型是否与您为其分配结果的变量的声明类型相匹配。所以它检查是否 String 火柴 K , 而如果 Map<Long, List<String>> 匹配V,他们这样做,因此它认为赋值是类型安全的,并生成基本上使用Map(无泛型)变量的字节码。
Map<String, Map<Long, List<String>>> map = getHashMap();
Map<String, Map<Long, List<String>>>
String
K
Map<Long, List<String>>
如果您已将您的方法声明为:
static <K extends Number,V> Map<K,V> getHashMap() { return new HashMap<K, V>(); }
在分析赋值时,编译器会看到 String 不匹配 K extends Number ,会抛出编译错误,并且不会为该赋值创建字节码。
K extends Number
class XX static <T> 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.<String> foo(); Integer i = XX.<Integer>foo();
但实际上,Java 的 使然 强> 那个返回类型 T 必须这样决定。
T
我发现这件事非常可疑,不确定设计背后的原因是什么。可能,当(if)Java添加可再生类型(即真正的类) T 在运行时可用),设计更有意义:
class XX static <T> T foo(){ return new T(); } String s = XX.foo(); Integer i = XX.foo();
我仍然不喜欢方法的类型依赖于上下文的事实。