昨天有朋友问我,IDEA调式HashMap,在调式下面代码的时候,entrySet一开始就有值了,但是没有找到给entrySet赋值的地方。
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
我写了段代码验证,发现确实如此,开始我以为是jdk1.8的原因,相同代码放到1.6后还是如此。
public class HashMapEntrySetTest {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("aaa","aaaa");
map.entrySet();
}
}
调式结果:
我在https://blog.csdn.net/lwj_zeal/article/details/72899934找到了答案,IDEA在调式的时候会调用对象的toString方法。验证代码如下:
public class DebugTest {
@Override
public String toString() {
System.out.println("======debug======");
return super.toString();
}
public static void main(String[] args) {
System.out.println("======start======");
DebugTest debugTest = new DebugTest();
}
}
不加debug输出结果是:======start======
在System.out.println("======start======");行加断点,单步执行时会多输出======debug======。也就是说IDEA在单步执行时会调用对象的toString方法。
现在再来看HashMap的toString方法,HashMap没有重写toString,而是在它的父类AbstractMap重写了。
public String toString() {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (! i.hasNext())
return "{}";
StringBuilder sb = new StringBuilder();
sb.append('{');
for (;;) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
sb.append(key == this ? "(this Map)" : key);
sb.append('=');
sb.append(value == this ? "(this Map)" : value);
if (! i.hasNext())
return sb.append('}').toString();
sb.append(',').append(' ');
}
}
从上面代码可以看到,在toString中有调用entrySet()方法,entrySet第一次赋值是在这里。
为了再次确认是IDEA的问题,我又在eclipse中调式entrySet方法,发现第一次进去的时候是为空。