美文网首页java我爱编程
Java内部类的使用

Java内部类的使用

作者: d3f59bfc7013 | 来源:发表于2018-05-24 20:58 被阅读0次

    在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

    内部类的定义其实一点都不难理解,但是较难理解的是什么时候该用内部类?该用内部类的哪种形式?这个可能是大部分人比较难以理解的。我在这里自己实现一个Java集合中的链式线性表MyLinkedList,然后结合这个实现来发表一下我对内部类的看法。

    MyLinkedList实现依赖于下列最基本的类。

        class Node<E> {
            E element;
            Node<E> next;
            
            public Node(E element) {
                this.element = element;
            }
        }
    

    现在需要考虑的是要将这个类定位成public 类,default 类,还是内部类?这个时候就需要分析这个类是用来干什么的。很明显它出现的目的就是为了服务MyLinkedList,其他类并不需要访问到这类,因此应该将这个数据这个类设计成内部类。
    <font color="red">这里反问一下,不设计成内部类可以么?</font>是可以的,但是由于Node类只用于LinkedList,所以为了数据封装,应该把它设计成内部类。所以更改如下:

        private class Node<E> {
            E element;
            Node<E> next;
            
            public Node(E element) {
                this.element = element;
            }
        }
    

    内部类还有静态和非静态内部类,这个类该设计成哪种?首先要明白静态内部类和非静态内部类的区别,下面是两者的区别

    • 内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用
    • 非静态内部类能够访问外部类的静态和非静态成员。静态类不能访问外部类的非静态成员。只能访问外部类的静态成员
    • 一个非静态内部类不能脱离外部类实体被创建,一个非静态内部类可以访问外部类的数据和方法,因为他就在外部类里面

    由于Node不需要访问MyLinkedList任何实例成员变量,所以它应该设计成静态内部类。

        private static class Node<E> {
            E element;
            Node<E> next;
            
            public Node(E element) {
                this.element = element;
            }
        }
    

    下面给出MyLinkedList的实现,里面还有一个非静态内部类LinkedListIterator。这个类为什么需要设计成非静态的?其实是因为它需要访问MyLinkedList的实例成员变量private Node<E> head, tail; ,如果把它改成静态内部类,会报错。可以在IDE里试试更改成静态内部类看看报错信息。

    MyLinkedList实现的接口

    public interface MyList<T> extends Iterable<T> {
        public void add(T t);
        public void add(int index,T t);
        public void clear();
        public boolean contains(T t);
        public T get(int index);
        public int indexOf(T e);
        public boolean isEmpty();
        public int lastIndexOf(T t);
        public boolean remove(T t);
        public T remove(int index);
        public Object set(int index,T t);
        public int size();
    }
    

    MyLinkedList继承的父类

    /**
     * @author: gethin
     * @create: 2018-05-22 15:21
     * @description: 
     **/
    public abstract class MyAbstrctList<E> implements MyList<E> {
        protected int size = 0;
        
        protected MyAbstrctList() {
        
        }
        
        protected MyAbstrctList(E[] objects) {
            for (int i = 0; i < objects.length; i++) {
                add(size, objects[i]);
            }
        }
        
        @Override
        public void add(E e) {
            add(size, e);
        }
        
        @Override
        public boolean isEmpty() {
            return size == 0;
        }
        
        @Override
        public boolean remove(E e) {
            if (indexOf(e) >= 0) {
                remove(indexOf(e));
                return true;
            } else {
                return false;
            }
        }
        
        @Override
        public int size() {
            return 0;
        }
        
    }
    

    MyLinkedList实现

    /**
     * @author: gethin
     * @create: 2018-05-24 10:55
     * @description: 我的链式线性表
     **/
    
    public class MyLinkedList<E> extends MyAbstrctList<E> {
        private Node<E> head, tail;
        
        public MyLinkedList() {
        
        }
        
        public MyLinkedList(E[] object) {
            super(object);
        }
        
        public E getFirst() {
            if (size == 0) {
                return null;
            } else {
                return head.element;
            }
        }
        
        public E getLast() {
            if (size == 0) {
                return null;
            } else {
                return tail.element;
            }
        }
        
        public void addFirst(E e) {
            Node<E> newNode = new Node<>(e);
            newNode.next = head;
            head = newNode;
            size++;
            if (tail == null) {
                tail = head;
            }
        }
        
        public void addLast(E e) {
            Node<E> newNode = new Node<>(e);
            if (tail == null) {
                head = tail = newNode;
            } else {
                tail.next = newNode;
                tail = tail.next;
            }
            size++;
        }
        
        public E removeFirst() {
            if (size == 0) {
                return null;
            } else {
                Node<E> temp = head;
                head = head.next;
                size--;
                if (head == null) {
                    tail = null;
                }
                return temp.element;
            }
        }
        
        public E removeLast() {
            if (size == 0) {
                return null;
            } else if (size == 1) {
                Node<E> temp = head;
                head = tail = null;
                size = 0;
                return temp.element;
            } else {
                Node<E> current = head;
                for (int i = 2; i < size - 2; i++) {
                    current = current.next;
                }
                Node<E> temp = tail;
                tail = current;
                tail.next = null;
                size--;
                return temp.element;
            }
        }
        
        
        @Override
        public void add(int index, E e) {
            if (index == 0) {
                addFirst(e);
            } else if (index >= size) {
                addLast(e);
            } else {
                Node<E> current = head;
                for (int i = 1; i < index; i++) {
                    current = current.next;
                }
                Node<E> temp = current.next;
                current.next = new Node<>(e);
                current.next.next = temp;
                size++;
            }
        }
        
        @Override
        public void clear() {
            head = tail = null;
            size = 0;
        }
        
        @Override
        public boolean contains(E e) {
            if (size == 0) return false;
            Node<E> current = head;
            do {
                if (current.element.equals(e)) {
                    return true;
                }
                current = current.next;
            } while (current != null);
            return false;
        }
        
        @Override
        public E get(int index) {
            if (index < 0 || index >= size) {
                return null;
            } else {
                Node<E> current = head;
                for (int i = 0; i < size; i++) {
                    if (index == size) {
                        break;
                    }
                    current = current.next;
                }
                return current.element;
            }
        }
        
        @Override
        public int indexOf(E e) {
            if (e == null) {
                return -1;
            }
            int index = 0;
            Node<E> current = head;
            for (; index < size; index++) {
                if (current.element.equals(e)) {
                    break;
                }
                current = current.next;
            }
            return index < size ? index : -1;
        }
        
        @Override
        public int lastIndexOf(E e) {
            if (e == null) {
                return -1;
            }
            int lastIndex = -1;
            Node<E> current = head;
            for (int i = 0; i < size; i++) {
                if (current.element.equals(e)) {
                    lastIndex = i;
                }
                current = current.next;
            }
            return lastIndex;
        }
        
        @Override
        public E remove(int index) {
            if (index == 0 || index >= size) {
                return null;
            } else if (index == 0) {
                return removeFirst();
            } else if (index == size - 1) {
                return removeLast();
            } else {
                Node<E> previous = head;
                for (int i = 1; i < index; i++) {
                    previous = previous.next;
                }
                Node<E> current = previous.next;
                previous.next = current.next;
                size--;
                return current.element;
            }
        }
        
        @Override
        public E set(int index, E e) {
            if (index < 0 || index > size) {
                return null;
            } else {
                Node<E> current = head;
                for (int i = 0; i < size; i++) {
                    if (index == i) {
                        break;
                    }
                    current = current.next;
                }
                E old = current.element;
                current.element = e;
                return old;
            }
        }
        
        @Override
        public String toString() {
            StringBuilder result = new StringBuilder("[");
            Node<E> current = head;
            for (int i = 0; i < size; i++) {
                result.append(current.element);
                current = current.next;
                if (current != null) {
                    result.append(", ");
                } else {
                    result.append("]");
                }
            }
            return result.toString();
        }
        
        @Override
        public Iterator iterator() {
            return new LinkedListIterator();
        }
        
        private class LinkedListIterator implements Iterator<E> {
            private Node<E> current = head;
            
            @Override
            public void remove() {
                Node<E> previous = head;
                while (previous.next != current) {
                    previous = previous.next;
                }
                previous.next = previous.next.next;
                size--;
            }
            
            @Override
            public boolean hasNext() {
                return current != null;
            }
            
            @Override
            public E next() {
                E e = current.element;
                current = current.next;
                return e;
            }
        }
        
        //This class is only used in MyLinkedList,so it is private.
        //This class is not need to access any instance numbers of MyLinkedList,so it is defined static 
        private static class Node<E> {
            E element;
            Node<E> next;
            
            public Node(E element) {
                this.element = element;
            }
        }
        
        public static void main(String[] args) {
            MyLinkedList<String> list = new MyLinkedList<>();
            list.add("zhangsan");
            list.add(1, "lisi");
            list.addLast("wangwu");
            list.add("lisi");
            System.out.println(list);
            System.out.println(list.contains("lisi"));
            System.out.println(list.indexOf("lisi"));
            System.out.println(list.lastIndexOf("lisi"));
            list.set(3, "lisi2");
            System.out.println(list);
            Iterator iterator = list.iterator();
            boolean flag = true;
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
                if (flag) {
                    iterator.remove();
                    flag = false;
                }
            }
            System.out.println(list);
        }
    }
    

    使用内部类的原因可以总结为:
    1. 如果一个类只对另一个类有用,那么将它嵌入该类并将它们保持在一起是合乎逻辑的。 嵌套这样的“帮助类”使得它们的包更加简化
    2. 它增加了封装:考虑两个顶级类A和B,其中B需要访问A的成员,否则这些成员将被声明为私有。通过在类A中隐藏类B,可以将A的成员声明为私有,并且B可以访问它们。 另外,B本身可以被外界隐藏起来
    3. 通过在类A中隐藏类B,可以将A的成员声明为私有,并且B可以访问它们。 另外,B本身可以被外界隐藏起来
    需要更加全面了解,可以访问Oracle官方教程链接

    相关文章

      网友评论

        本文标题:Java内部类的使用

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