理解java Foreach

1,定义容器能够foreach遍历
2.分析使用Arraylist foreach遍历时移除数据异常

java容器都具有用于遍历数据的foreach功能,如果自己定义一个容器类,如何实现这个语法呢?

第一步:实现Iterable接口

实现接口就要实现内部的方法(java8 default修饰的方法无需实现)

public class ForEachClass<T> implements Iterable<T> {
    @Override
    public Iterator iterator() {
        return null;
    }
}

第二步:实现接口方法

因为接口返回iterator对象,所以需要iterator是一个接口,所以必须定义一个实现iterator接口的类,然后实例化后成为对象再返回.

public class TestForEach {

    //注1:T泛型作为该自定义容器数据的类型
    static class ForEachClass<T> implements Iterable<T> {
        Object[] value = null;
        int current = 0;
        //用于测试
        public void addvalue(T... t) {
            value = t;
        }
        //注2:每次foreach都会调用该方法
        @Override
        public Iterator<T> iterator() {
            current = 0;
            //参考list,用到是new,所以应该没问题
            return new It();
        }

注1:这里Iterable的泛型就是foreach中遍历数据所对应的类型.
注2:实现Iterable接口

Iterator是一个接口,需要自定义Iterator实现类,实现其hasNext和next方法

        private class It implements Iterator<T> {
            //注3:是否存在下一个元素,foreach停止的判断条件
            @Override
            public boolean hasNext() {
                return value != null && current < value.length;
            }
            //注4:返回一下一个元素,作为foreach输出
            @Override
            public T next() {
                T t = (T) value[current];
                current++;
                return t;
            }
        }
    }
}

注3:是否存在下一个元素,foreach停止的判断条件
注4:返回一下一个元素,作为foreach输出

foreach遍历

        ForEachClass<Integer test = new ForEachClass();
        test.addvalue(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        for (Integer a : test) {//测试
            System.out.print(a + " ");
        }

迭代器遍历数据

当这个容器类可以通过foreach遍历数据后,这个类也能通过迭代器遍历数据

        Iterator iterator =test.iterator();//注1,上步实现的接口
        while(iterator.hasNext()){//注2:上步实现iterator接口的hasNext
            Intenger i = iterator.next();//注3:上步实现iterator接口的next
            }
        }

注1,上步实现的接口
注2:上步实现iterator接口的hasNext
注3:上步实现iterator接口的next
上面3个方法均在实现foreach的时候实现了

foreach中删除数据报错

在list中,remove一个数据会导致foreach报ConcurrentModificationException异常
因为foreach会调用迭代器中next方法,next方法会调用checkForComodification,

public E next() {
       checkForComodification(); 
       ....
}
final void checkForComodification() {
if (modCount != expectedModCount)
       throw new ConcurrentModificationException();
}

因为list在remove和add的时候会改变modCount的值,expectedModCount只会在foeach开始赋值,在foreach每次调用next都会比较这两个值,看是否相等,如果不等就报错.估计设计这个的工程师只想让foreach只能作为遍历数据使用,防止出现其他的bug,毕竟foreach的细节不可见.如果要在遍历过程中删除和数据,可以使用迭代器.如下;

        Iterator iterator =test.iterator();
        while(iterator.hasNext()){
            if (iterator.next().equals("3")){
                iterator.remove();
            }
        }

除了容器类可以使用foreach遍历数据,数组也能通过这种方式遍历,如:

String[] arg =new String[10];
for(String s:arg) {
///XXXX
}

数组结构比较简单,而且没有方法,只有通过length知道大小,通过下标访问和写入,编译器就很轻松处理数组的foreach语法.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章