Java中entrySet相关疑问:为何调用getKey()的代码可正常运行?
问题背景
以下是一段Java代码:
// Using entrySet() to get the entry's of the map // m is previously created Map. Set<Map.Entry<String,Integer>> s = m.entrySet(); for (Map.Entry<String, Integer> it: s) { String str = it.getKey(); }
已知:
Map.Entry仅为一个接口。- 接口本身并没有
getKey();方法的实现。
请问为何上述代码能够正常运行?编译器是如何知晓getKey()方法的行为的?
问题解答
这其实是Java多态特性和集合框架设计逻辑的结合,咱们一步步拆解清楚:
entrySet()返回的是接口的具体实现实例
你代码里的m肯定是某个Map接口具体实现类的对象(比如HashMap、TreeMap这些常用实现)。这些Map实现类内部都自带了Map.Entry接口的具体实现类——比如HashMap里的Node内部类,它不仅实现了Map.Entry接口,还完整写好了getKey()、getValue()等方法的执行逻辑。编译器只关心静态类型的方法声明
编译阶段,编译器看到变量it的静态类型是Map.Entry<String, Integer>,它只会去校验Map.Entry接口里有没有声明getKey()方法——而Map.Entry接口本身就明确定义了K getKey();这个抽象方法,所以编译器会判定这段代码合法,不会抛出编译错误。运行时才会调用实际对象的实现逻辑
到了程序运行阶段,JVM会根据it指向的实际对象类型(比如HashMap$Node),调用该对象中已经实现好的getKey()方法。这就是多态的核心:接口负责定义规范,具体实现类提供执行逻辑,编译看接口、运行看实际对象。
举个直观的例子,HashMap源码里的Node类(简化版)就是这么实现的:
static class Node<K,V> implements Map.Entry<K,V> { final K key; V value; Node<K,V> next; int hash; // 构造方法等... @Override public K getKey() { return key; } @Override public V getValue() { return value; } }
当你调用HashMap的entrySet()时,返回的集合里全是这种Node对象,它们已经把getKey()的实现逻辑写死了,所以运行时调用完全没问题。
内容的提问来源于stack exchange,提问作者Lin Paul

