美文网首页
java增强型for循环

java增强型for循环

作者: small瓜瓜 | 来源:发表于2019-07-07 08:56 被阅读0次

    增强型for循环是jdk1.5的新特性,使用更加方便,书写简洁。

    比如:

            int[] as = {
                    1,2,3,5
            };
            for (int a : as) {
                System.out.println("a = " + a);
            }
    

    在比如:

            List<Integer> integerList = new ArrayList<>();
            for (Integer integer : integerList) {
                System.out.println("integer = " + integer);
            }
    

    用这种方式代码更加简洁,可读性强。
    这么方便的东西我们怎么能放过呢?接下来就一起实现一个自己的增强型for循环吧
    首先看看List的继承图:



    最上层是一个Iterable接口。看看它的源码注释的描述:

    Implementing this interface allows an object to be the target of the "for-each loop" statement. See For-each Loop

    显然这就是可以使用for循环的原因了,先贴出Iterable源码,接下来我们编写一个类来实现这个接口。

    public interface Iterable<T> {
        /**
         * Returns an iterator over elements of type {@code T}.
         *
         * @return an Iterator.
         */
        Iterator<T> iterator();
    
        /**
         * Performs the given action for each element of the {@code Iterable}
         * until all elements have been processed or the action throws an
         * exception.  Unless otherwise specified by the implementing class,
         * actions are performed in the order of iteration (if an iteration order
         * is specified).  Exceptions thrown by the action are relayed to the
         * caller.
         *
         * @implSpec
         * <p>The default implementation behaves as if:
         * <pre>{@code
         *     for (T t : this)
         *         action.accept(t);
         * }</pre>
         *
         * @param action The action to be performed for each element
         * @throws NullPointerException if the specified action is null
         * @since 1.8
         */
        default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
    
        /**
         * Creates a {@link Spliterator} over the elements described by this
         * {@code Iterable}.
         *
         * @implSpec
         * The default implementation creates an
         * <em><a href="Spliterator.html#binding">early-binding</a></em>
         * spliterator from the iterable's {@code Iterator}.  The spliterator
         * inherits the <em>fail-fast</em> properties of the iterable's iterator.
         *
         * @implNote
         * The default implementation should usually be overridden.  The
         * spliterator returned by the default implementation has poor splitting
         * capabilities, is unsized, and does not report any spliterator
         * characteristics. Implementing classes can nearly always provide a
         * better implementation.
         *
         * @return a {@code Spliterator} over the elements described by this
         * {@code Iterable}.
         * @since 1.8
         */
        default Spliterator<T> spliterator() {
            return Spliterators.spliteratorUnknownSize(iterator(), 0);
        }
    }
    

    看源码知道实现这个接口,要实现方法iterator,返回值是Iterator<T>,这又是一个接口,我们可以在定义的类的内部编写内部类实现Iterator<T>。
    下面贴出实现代码:

    import java.util.Iterator;
    
    public class MyList implements Iterable<Integer> {
    
        private Integer[] integers;
    
        public MyList(Integer[] integers) {
            this.integers = integers;
        }
    
        @Override
        public Iterator<Integer> iterator() {
            return new MyIterable();
        }
    
        class MyIterable implements Iterator<Integer> {
            private int index;
    
            @Override
            public boolean hasNext() {
                return index < integers.length;
            }
    
            @Override
            public Integer next() {
                return integers[index++];
            }
        }
    }
    

    编写以下代码进行测试:

            MyList integers = new MyList(new Integer[]{1, 2, 3});
            for (Integer integer : integers) {
                System.out.println("integer = " + integer);
            }
    

    到此就实现了自己的可使用增强型for循环的类,为了能更深入的理解,不妨给自己提一个问题。为什么可以这样,我们最开始学习java语法规则就只学过三种循环for(;;),while(),do{}while(),这个新出来的循环是怎么实现的呢?jvm层面还是编译器层面?
    接下来我们来看看上面写的代码反编译后的样子(idea反编译):

            MyList integers = new MyList(new Integer[]{1, 2, 3});
            Iterator var2 = integers.iterator();
    
            while(var2.hasNext()) {
                Integer integer = (Integer)var2.next();
                System.out.println("integer = " + integer);
            }
    
    idea反编译代码

    其实我们编写的代码是编译器帮我们转换成了传统的循环了,这就是为什么要实现Iterable和Iterator接口了。
    但是问题又来了,数组为什么可以用增强型for循环呢?它并没有实现这些接口啊,而且也不可能有next,hasNext方法。它是怎么实现的呢?
    编写以下例子:

        public static void main(String[] args) {
            int[] as = {
                    1,2,3,5
            };
            for (int a : as) {
                System.out.println("a = " + a);
            }
        }
    

    下面是它反编译后的代码:

        public static void main(String[] args) {
            int[] as = new int[]{1, 2, 3, 5};
            int[] var2 = as;
            int var3 = as.length;
    
            for(int var4 = 0; var4 < var3; ++var4) {
                int a = var2[var4];
                System.out.println("a = " + a);
            }
        }
    

    看到这里所有迷团都解开了,简单说,对于JVM来说,增强型for循环其实就是传统循环。只是对于程序员来说有了变化。
    这属于"挂羊头买狗肉"吗,哈哈,不过这样的确方便了不少,如果让我们写上反编译后的代码,那是有多麻烦啊。

    相关文章

      网友评论

          本文标题:java增强型for循环

          本文链接:https://www.haomeiwen.com/subject/pmgvhctx.html