今天突然想看看foreach内部实现是怎样的,比如如下代码:
for (EmailClientEntity emailClient : emailClientDao.findAll()) {
//TODO something...
}
通过javap看看字节码指令:
public void initAllEmailSession();
Code:
0: aload_0
1: getfield #9 // Field emailClientDao:Lcom/xxx/unionloan/dao/EmailClientDao;
4: invokeinterface #10, 1 // InterfaceMethod com/xxx/unionloan/dao/EmailClientDao.findAll:()Ljava/util/List;
9: invokeinterface #11, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
14: astore_1
15: aload_1
16: invokeinterface #12, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
21: ifeq 98
24: aload_1
25: invokeinterface #13, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
30: checkcast #14 // class com/xxx/unionloan/entity/EmailClientEntity
33: astore_2
34: aload_0
35: getfield #8 // Field storeMap:Ljava/util/Map;
38: aload_2
39: invokevirtual #15 // Method com/xxx/unionloan/entity/EmailClientEntity.getEmailAddress:()Ljava/lang/String;
42: new #16 // class java/util/Properties
45: dup
46: invokespecial #17 // Method java/util/Properties."<init>":()V
49: aconst_null
50: invokestatic #18 // Method javax/mail/Session.getDefaultInstance:(Ljava/util/Properties;Ljavax/mail/Authenticator;)Ljavax/mail/Session;
53: ldc #19 // String imap
55: invokevirtual #20 // Method javax/mail/Session.getStore:(Ljava/lang/String;)Ljavax/mail/Store;
58: invokeinterface #21, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
63: pop
64: aload_0
65: getfield #8 // Field storeMap:Ljava/util/Map;
68: aload_2
69: invokevirtual #15 // Method com/xxx/unionloan/entity/EmailClientEntity.getEmailAddress:()Ljava/lang/String;
72: invokeinterface #22, 2 // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
77: checkcast #23 // class javax/mail/Store
80: aload_2
81: invokevirtual #24 // Method com/xxx/unionloan/entity/EmailClientEntity.getSmtpHost:()Ljava/lang/String;
84: aload_2
85: invokevirtual #15 // Method com/xxx/unionloan/entity/EmailClientEntity.getEmailAddress:()Ljava/lang/String;
88: aload_2
89: invokevirtual #25 // Method com/xxx/unionloan/entity/EmailClientEntity.getEmailPassword:()Ljava/lang/String;
92: invokevirtual #26 // Method javax/mail/Store.connect:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
95: goto 15
98: goto 113
101: astore_1
102: getstatic #28 // Field log:Lorg/slf4j/Logger;
105: ldc #29 // String 数据库的邮箱配置不正确!
107: aload_1
108: invokeinterface #30, 3 // InterfaceMethod org/slf4j/Logger.error:(Ljava/lang/String;Ljava/lang/Throwable;)V
113: return
Exception table:
from to target type
0 98 101 Class java/lang/Exception
可以看到标红部分的意思:
第1个引用型变量进栈
获取对象的字段emailClientDao,将其值压入栈顶
调用接口方法EmailClientDao.findAll:()保存到第2局部变量
调用接口方法的List.iterator:()保存第2局部变量
栈顶引用对象存入第2局部变量
第2个引用型变量进栈
调用接口方法Iterator.hasNext()保存结果到第二局部变量
看出来foreach的内部实现是获取集合的迭代器来实现的。