JAVA for-each原理

本文详细解释了Java中for-each循环的工作原理及其适用场景。包括数组和实现了Iterable接口的对象如何被for-each循环遍历,并提供了一个自定义可遍历类的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们在写程序的时候经常使用for-each来遍历对象。那么为什么有些对象可以通过for-each来遍历呢我们的自定义类在不继承于集合对象的情况下,是否可以遍历呢

  • 什么是for-each

    for-each是增强型的for循环,是java提供的一种语法糖。

    for (int i = 0; i < list.size; i ++) {
        Object obj = list.get(i);
    }
    

    简化成

    for (Object obj: list){
    }
    

  • 为什么可以被for-each遍历

    可以被foreach遍历的对象分两种情况:

  1. 数组
    java对于数组的for-each处理相对简单。只是在编译期把for-each还原成简单的for循环

    源代码:

    Object[] list = new Object[10];
    for (Object obj: list){
    }
    

    用工具反编译class文件之后的代码:

    Object[] list = new Object[10];
    Object[] var14 = list;
    int var15 = list.length;
        
    for (int var16 = 0; var16 < var15; ++var16) {
       Object var10000 = var14[var16];
    }
    

    java对于数组的for-each处理相对简单。只是在编译期把for-each还原成简单的for循环

  2. 实现 Iterable 接口的对象
    实现了Iterable的对象,可以被for-each。并且最终java会通过迭代器的形式来遍历它
    我们以ArrayList为例(ArrayList实现了Iterable接口)。

    源代码:

    List<Object> list = new ArrayList();
    for (Object obj: list){
    }
    

    用工具反编译class文件之后的代码:

    List<Object> list = new ArrayList();
    
    Object var15;
    for (Iterator var14 = list.iterator(); var14.hasNext(); var15 = var14.next()) {
        ;
    }
    

    实现了Iterable的对象,可以被for-each。并且最终java会通过迭代器的形式来遍历它


  • Iterable 接口
    对于ArrayList集合的for-each遍历,java并没有像数组一样简单的还原成for (int i = 0; i < list.size; i ++),而是使用了迭代器来遍历集合。这是为什么呢?

    我们来看看Iterable接口的用途是什么。

    /**
    * Implementing this interface allows an object to be the target of
    * the "for-each loop" statement. See
    * <strong>
    * <a href="{@docRoot}/../technotes/guides/language/foreach.html">For-each Loop</a>
    * </strong>
    *
    * @param <T> the type of elements returned by the iterator
    *
    * @since 1.5
    * @jls 14.14.2 The enhanced for statement
    */
    public interface Iterable<T> {
    }
    

    有一段很简单的英文注释:

    实现了这个接口(Iterable)允许对象成为for-each的目标。


  • 自定义一个可以for-each的类

    仿照ArrayList写一个简单的可遍历类。

    public class IterableTester<S> implements Iterable<S>{
    
        private Object[] elementData = {};
    
        private int size = 0;
    
        public IterableTester(int initialCapacity) {
            if ( initialCapacity > 0) {
                elementData = new Object[initialCapacity];
            }
        }
    
        /**
        * 添加方法,返回true/false表明是否成功
        */
        public boolean add(S element) {
            if (size < elementData.length) {
                elementData[size] = element;
                size++;
                return true;
            } else {
                //超出容量,返回false
                return false;
            }
        }
    
        @Override
        public Iterator<S> iterator() {
            return new Itr();
        }
    
        //内部类,实现Interator接口,这样就可以使用迭代器遍历
        private class Itr implements Iterator<S> {
            int cursor;
    
            @Override
            public boolean hasNext() {
                //如果当前index不等于于size,说明还有下一个
                return cursor != size;
            }
    
            @Override
            public S next() {
                int i = cursor;
                if (i >= size)
                    throw new RuntimeException();
                Object[] elementData = IterableTester.this.elementData;
                if (i >= elementData.length)
                    throw new RuntimeException();
                cursor = i + 1;
                return (S) elementData[i];
            }
        }
    
    }
    
    

    这里实现了一个很简单的可遍历类,不考虑扩容等情况。
    执行for-each的时候,会首先调用 iterator 方法,返回一个新的迭代器。然后调用迭代器的 hasNextnext 方法来进行遍历。

    接下来我们写一段测试代码,简单跑一下。

    IterableTester<String> iterableTester = new IterableTester<>(5);
    System.out.println(iterableTester.add("1111"));
    System.out.println(iterableTester.add("2222"));
    System.out.println(iterableTester.add("3333"));
    System.out.println(iterableTester.add("4444"));
    System.out.println(iterableTester.add("5555"));
    //超出容量,打印出来的是false
    System.out.println(iterableTester.add("6666"));
    
    for (String str: iterableTester) {
        System.out.println(str);
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值