美文网首页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 内部类和泛型的理解

    Java 内部类 Java非静态内部类持有对外部类的引用,可以访问外部类的状态使用方法 OuterClass.th...

  • 内部类

    内部类可以分为:非静态内部类;静态内部类;匿名内部类。 一、内部类 首先要说,Java为什么要使用内部类?java...

  • Java 中的方法内部类

    Java 中的方法内部类 方法内部类就是内部类定义在外部类的方法中,方法内部类只在该方法的内部可见,即只在该方法内...

  • Kotlin-Object关键字作用

    Object关键字使用场景:匿名内部类、单例、伴生对象。 匿名内部类 Kotlin匿名内部类定义使用跟Java类似...

  • PHP转JAVA的记录

    Java 数组 内部类 内部类的创建:内部类可以对包内其他类隐藏想实现一个接口时, 不想新建类文件 内部类可以访问...

  • java内部类

    一、内部类为什么存在 为什么要使用内部类 二、内部类的分类 java内部类的分类 三、为什么内部类中访问局部变量,...

  • 2017-10-12

    这是我学习Java内部类的笔记 1.为什么使用内部类? 使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(...

  • 那为何要使用匿名内部类

    那为何要使用匿名内部类 Think in java上说:使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(...

  • android 内存泄漏的初级见识

    内部类的使用 java的非静态内部类和匿名内部类会默认包含外部类的引用,因此在非静态(或匿名)内部类中我们可以直接...

  • 【Java】内部类与外部类的互访使用小结

    原博客链接:【Java】内部类与外部类的互访使用小结 内部类又称为嵌套类。可以把内部类理解为外部类的一个普通成员。...

网友评论

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

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