Think In Java——容器深入研究之CountingIntegerList

先po上代码

import java.util.*;

public class CountingIntegerList extends AbstractList<Integer> {
    private int size;

    public CountingIntegerList(int size) {
        this.size = size < 0 ? 0 : size;
    }

    public Integer get(int index) {
        return Integer.valueOf(index);
    }

    public int size() {
        return size;
    }

    public static void main(String[] args) {
        System.out.println(new CountingIntegerList(30));
    }


} /* Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
*///:~

它的输出居然是[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]。

开debug模式逐语句分析下

                                              

发现程序多次使用get()和size()方法 ,跳进去看看。

 ,

看到AbstractList的内部类Itr的hasNext()使用了size(),next()使用了get(),基本就能猜到了。下面是这段代码的解析。

 public static void main(String[] args) {
        System.out.println(new CountingIntegerList(30));
    }

System.out.println()会调用CountingIntegerList的toString()方法。那就看看它父类的toString()吧。在它父类的父类AbstractCollection找到了toString()的实现。

/**
     * Returns a string representation of this collection.  The string
     * representation consists of a list of the collection's elements in the
     * order they are returned by its iterator, enclosed in square brackets
     * (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
     * <tt>", "</tt> (comma and space).  Elements are converted to strings as
     * by {@link String#valueOf(Object)}.
     *
     * @return a string representation of this collection
     */
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

看到E e = it.next()这一行,打个断点进去看next()的实现(ctrl+左键是看不到的)

public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

再看到E next = get(i),没错,它调用的是我们重载的get()不断地返回Integer。那为什么返回的上限是29呢。我们回头看toString()中if (! it.hasNext())这行,进入hasNext()方法

public boolean hasNext() {
            return cursor != size();
        }

再进入size(),发现这是我们重载的size(),它返回的是30,所以打印数字的范围是0到29。

猜你喜欢

转载自blog.csdn.net/chaos_le/article/details/81510366