迭代器,Java嵌套类和内部类

来源:互联网 发布:淘宝申请开网店要钱吗 编辑:程序博客网 时间:2024/05/08 03:06

这里模拟ArrayList的实现为避免和系统的集合重名,这里使用MyArrayList作为类名。

public class MyArrayList<T> implements Iterable<T> {    private int thesize;    private T[] theItems;    ...    public int size() {        return theItems.length;    }    @Override    public Iterator<T> iterator() {        // TODO Auto-generated method stub        return new ArrayListIterator();    }    class ArrayListIterator implements Iterator<T> {        private int current = 0;        @Override        public boolean hasNext() {            return current<size();        }        @Override        public T next() {            // TODO Auto-generated method stub            return theItems[current++];        }        @Override        public void remove() {        }        ...    }}

这里存在一个问题,就是theItems[current ++]的使用时非法的,因为theItems不是ArrayListIterator的成员,而是MyArrayList 的成员。最简单的解决办法如下代码所示:

public class MyArrayList<T> implements Iterable<T> {    private int thesize;    private T[] theItems;    ...    public int size() {        return theItems.length;    }    @Override    public Iterator<T> iterator() {        // TODO Auto-generated method stub        return new ArrayListIterator();    }    class ArrayListIterator implements Iterator<T> {    int MyArrayList<T> thelist;    public ArrayListIterator(MyArrayList<T> thelist){    this.thelist=thelist;    }        private int current = 0;        @Override        public boolean hasNext() {            return current<thelist.size();        }        @Override        public T next() {            // TODO Auto-generated method stub            return thelist.theItems[current++];        }        @Override        public void remove() {        }        ...    }}

这种方式是通过内部类的构造函数保存MyArrayList的链,通过这个链就可以访问包含于MyArrayList中的数组和其他方法。问题是,theItems是MyArrayList中的私有成员,而ArrayListIterator是一个不同的类,因此在next方法中访问theItems是非法的。最简单的修改办法就是讲theItems的可见性修改为稍微宽松一点的权限控制符,如default public 。但是这又违反了面向对象编程中要求数据尽可能隐蔽。

下面再给出一个一种方案(嵌套内部类):

public class MyArrayList<T> implements Iterable<T> {    private int thesize;    private T[] theItems;    ...    public int size() {        return theItems.length;    }    @Override    public Iterator<T> iterator() {        // TODO Auto-generated method stub        return new ArrayListIterator();    }    private static class ArrayListIterator implements Iterator<T> {    int MyArrayList<T> thelist;    public ArrayListIterator(MyArrayList<T> thelist){    this.thelist=thelist;    }        private int current = 0;        @Override        public boolean hasNext() {            return current<thelist.size();        }        @Override        public T next() {            // TODO Auto-generated method stub            return thelist.theItems[current++];        }        @Override        public void remove() {        }        ...    }}

该方案中ArrayListIterator被实现为一个嵌套类。既然有了嵌套类,那么现在讨论下内部类。当申明一个内部类的时候,编译器会添加一个外部类对象的一个隐式引用,该引用引起内部类的构造。如果外部类的名字是Outer,则隐式引用就是outer.this。因此,如果ArrayListIterator是作为一个内部类被申明且没有注明static,那么MyArrayList.this和theList都会引用同一个MyArrayList。这样,thelist就多余了,并可能被删除。
在一个内部类对象恰好与一个外部类对象关联的情况下,内部类是有用的。这里给出MyArrayList类和迭代器之间的关系,此时这些内部类都用来实现这些迭代器。
这里写图片描述
theList.theItems可以替换成MyArrayList.this.theItems,等等。

对于嵌套内部类,有于它的创见不依赖于外部类对象。因此上面给出的方式是可行的。

0 0