1. 程式人生 > >JAVA的四種內部類及為什麼要用內部類

JAVA的四種內部類及為什麼要用內部類

        最近在看java的原始碼,但是時長能看一個類中都會有幾個內部類比如LinkedList中
private class ListItr implements ListIterator<E> {
        private Node<E> lastReturned;
        private Node<E> next;
        private int nextIndex;
        private int expectedModCount = modCount;

        ListItr(int index) {
            // assert isPositionIndex(index);
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }

        public boolean hasNext() {
            return nextIndex < size;
        }

        public E next() {
            checkForComodification();
            if (!hasNext())
                throw new NoSuchElementException();

            lastReturned = next;
            next = next.next;
            nextIndex++;
            return lastReturned.item;
        }

        public boolean hasPrevious() {
            return nextIndex > 0;
        }

        public E previous() {
            checkForComodification();
            if (!hasPrevious())
                throw new NoSuchElementException();

            lastReturned = next = (next == null) ? last : next.prev;
            nextIndex--;
            return lastReturned.item;
        }

        public int nextIndex() {
            return nextIndex;
        }

        public int previousIndex() {
            return nextIndex - 1;
        }

        public void remove() {
            checkForComodification();
            if (lastReturned == null)
                throw new IllegalStateException();

            Node<E> lastNext = lastReturned.next;
            unlink(lastReturned);
            if (next == lastReturned)
                next = lastNext;
            else
                nextIndex--;
            lastReturned = null;
            expectedModCount++;
        }

        public void set(E e) {
            if (lastReturned == null)
                throw new IllegalStateException();
            checkForComodification();
            lastReturned.item = e;
        }

        public void add(E e) {
            checkForComodification();
            lastReturned = null;
            if (next == null)
                linkLast(e);
            else
                linkBefore(e, next);
            nextIndex++;
            expectedModCount++;
        }

        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            while (modCount == expectedModCount && nextIndex < size) {
                action.accept(next.item);
                lastReturned = next;
                next = next.next;
                nextIndex++;
            }
            checkForComodification();
        }

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

    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

然後就開始想為什麼java本身中要用內部類呢?

首先介紹下四種內部類

  • 成員內部類
  • 靜態內部類
  • 區域性內部類
  • 匿名內部類

一 成員內部類

1.沒有使用static修飾的內部類。
2.在成員內部類中不允許出現靜態變數和靜態方法的宣告。static只能用在靜態常量的宣告上。
3.成員內部類中可以訪問外部類中所有的成員(變數,方法),包含私有成員,如果在內部類中定義有和外部類同名的例項變數,訪問:OuterClass.this.outerMember;
4.構建內部類的例項,要求必須外部類的例項先存在
外部類的外部/外部類的靜態方法:new Outer().new Inner();

外部類的例項方法:new Inner();this.new Inner();

二 靜態內部類

1.宣告在類體部,方法體外,並且使用static修飾的內部類
2.訪問特點可以類比靜態變數和靜態方法
3.脫離外部類的例項獨立建立
 在外部類的外部構建內部類的例項 new Outer.Inner();
 在外部類的內部構建內部類的例項 new Inner();

 4.靜態內部類體部可以直接訪問外部類中所有的靜態成員,包含私有

三 區域性內部類

 1.定義在方法體,甚至比方法體更小的程式碼塊中
 2.類比區域性變數。
 3.區域性內部類是所有內部類中最少使用的一種形式。
 4.區域性內部類可以訪問的外部類的成員根據所在方法體不同。
 如果在靜態方法中:可以訪問外部類中所有靜態成員,包含私有
 如果在例項方法中:

可以訪問外部類中所有的成員,包含私有。

 區域性內部類可以訪問所在方法中定義的區域性變數,但是要求區域性變數必須使用final修飾。

四 匿名內部類

 1.沒有名字的區域性內部類。
 2.沒有class,interface,implements,extends關鍵字
 3.沒有構造器。

 4.一般隱式的繼承某一個父類或者實現某一個介面

介紹完四種內部類後來說下我理解的為什麼要用內部類

1 起到更好的封裝作用,不讓你知道具體實現細節,神祕感很足,比如:

private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

這個就是LinkedList中的內部類,也是連結串列結果的實現所需要的類

2 能巧妙躲過java中只能單繼承的弊端,比如:

private class DescendingIterator implements Iterator<E> {
        private final ListItr itr = new ListItr(size());
        public boolean hasNext() {
            return itr.hasPrevious();
        }
        public E next() {
            return itr.previous();
        }
        public void remove() {
            itr.remove();
        }
    }
這個內部類+介面就很好的實現了多繼承