先看代码
package collect; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class myiterator { public static void main(String[] args) { List<String> list =new ArrayList<String>(); list.add("China"); list.add("hello"); list.add("world"); System.out.println(list.size()); System.out.println(list); for (String str:list) { System.out.println(list); } } }
输出结果
3
[China, hello, world]
[China, hello, world]
[China, hello, world]
看字节码
// access flags 0x9 public static main([Ljava/lang/String;)V L0 LINENUMBER 9 L0 NEW java/util/ArrayList DUP INVOKESPECIAL java/util/ArrayList.<init> ()V ASTORE 1 L1 LINENUMBER 10 L1 ALOAD 1 LDC "China" INVOKEINTERFACE java/util/List.add (Ljava/lang/Object;)Z POP L2 LINENUMBER 11 L2 ALOAD 1 LDC "hello" INVOKEINTERFACE java/util/List.add (Ljava/lang/Object;)Z POP L3 LINENUMBER 12 L3 ALOAD 1 LDC "world" INVOKEINTERFACE java/util/List.add (Ljava/lang/Object;)Z POP L4 LINENUMBER 13 L4 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; ALOAD 1 INVOKEINTERFACE java/util/List.size ()I INVOKEVIRTUAL java/io/PrintStream.println (I)V L5 LINENUMBER 15 L5 ALOAD 1 INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator; ASTORE 3 GOTO L6 L7 FRAME FULL [[Ljava/lang/String; java/util/List T java/util/Iterator] [] ALOAD 3 INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object; CHECKCAST java/lang/String ASTORE 2 L8 LINENUMBER 16 L8 GETSTATIC java/lang/System.out : Ljava/io/PrintStream; ALOAD 1 INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V L6 LINENUMBER 15 L6 FRAME SAME ALOAD 3 INVOKEINTERFACE java/util/Iterator.hasNext ()Z IFNE L7 L9 LINENUMBER 19 L9 RETURN L10 LOCALVARIABLE args [Ljava/lang/String; L0 L10 0 LOCALVARIABLE list Ljava/util/List; L1 L10 1 // signature Ljava/util/List<Ljava/lang/String;>; // declaration: java.util.List<java.lang.String> LOCALVARIABLE str Ljava/lang/String; L8 L6 2 MAXSTACK = 2 MAXLOCALS = 4
可以看出内部使用了Iterator,forEach的内部实现原理是用的iterator,所以使用规则受iterator所限制,
比如内部list.add跟remove会报错Exception in thread "main" Java.util.ConcurrentModificationException
这也是找到原因了 iterator报错原因看这篇文章http://blog.youkuaiyun.com/mint6/article/details/77680061
使用forEach需要注意两点
1.使用foreach循环的对象,必须实现Iterable<T>接口,(Iterable每次调用都会返回一个从头开始计数的迭代器,解决Collection直接实现Iterator接口,导致当集合在不同方法间被传递时,当前迭代位置不可预置,那么next()方法的结果会变成不可预知的矛盾。)
方法:所有内置Collection类都实现了java.util.Collection接口,已经继承了Iterable
如果没有继承的,让所遍历的对象实现Collection接口或者继承AbstractCollection就可以了
2.内部实现原理使用iterator,所以注意遍历过程中的add跟remove操作