为何存储pupils的arr[0]调用entrySet()无法正常运行?
核心原因:原始类型数组导致的编译类型不兼容
你定义的Map[] arr是原始类型数组,尽管arr[0]在运行时实际指向泛型Map<String,Integer>对象,但编译阶段arr[0]的静态类型是不带泛型参数的原始Map。此时调用arr[0].entrySet()返回的是原始类型Set,而增强for循环指定的遍历类型是Map.Entry<?,?>——原始类型集合与泛型Map.Entry不兼容,因此编译报错。
反观直接用pupils.entrySet()的情况:pupils的静态类型是泛型Map<String,Integer>,调用entrySet()返回Set<Map.Entry<String,Integer>>,该泛型集合与Map.Entry<?,?>兼容,所以增强for循环可正常编译运行。
为什么引用相等但还是报错?
System.out.println(pupils.entrySet() == arr[0].entrySet())返回true是运行时结果:arr[0]的实际引用就是pupils对象,两次调用entrySet()返回同一个集合对象。但编译阶段的类型检查只看变量静态类型,与运行时实际对象无关,因此编译时的类型不兼容问题依然存在,代码无法进入运行阶段。
解决方案
方案1:使用带通配符的泛型数组
将数组定义为泛型类型,让arr[0]的静态类型变为Map<?,?>,调用entrySet()会返回Set<Map.Entry<?,?>>,与遍历类型兼容:
Map<String, Integer> pupils = new HashMap<>(); Map<String, Integer> teachers = new HashMap<>(); pupils.put("Alex", 12); pupils.put("Joe", 11); teachers.put("Helen", 28); teachers.put("Michael", 29); Map<?, ?>[] arr = new Map<?, ?>[2]; arr[0] = pupils; arr[1] = teachers; // 可正常运行 for (Map.Entry<?, ?> me : arr[0].entrySet()){ System.out.println(me.getKey() + " - " + me.getValue()); }
方案2:强制转换为泛型Map后遍历
保留原始数组定义,遍历前将arr[0]强制转换为泛型Map<?,?>,让编译阶段识别正确的泛型类型:
Map[] arr = new Map[2]; arr[0] = pupils; arr[1] = teachers; // 先转换为泛型Map Map<?, ?> map = arr[0]; for (Map.Entry<?, ?> me : map.entrySet()){ System.out.println(me.getKey() + " - " + me.getValue()); }
方案3:用List替代数组(推荐)
Java对泛型集合的支持比泛型数组更完善,使用List可彻底避免原始类型带来的问题:
List<Map<String, Integer>> list = new ArrayList<>(); list.add(pupils); list.add(teachers); for (Map.Entry<?, ?> me : list.get(0).entrySet()){ System.out.println(me.getKey() + " - " + me.getValue()); }
内容的提问来源于stack exchange,提问作者Coocoociki

