You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求提供JDK、JRE中内部类、嵌套类等的实际使用示例

嘿,这问题提得太实在了!很多人学内部类的时候光抠语法,却不知道JDK/JRE里其实到处都是它们的身影——毕竟这些特性就是为了更好地封装逻辑、优化代码结构而生的。我整理几个最典型的官方实际案例,都是你日常写代码可能天天打交道的:

1. 静态嵌套类(Static Nested Class)

最经典的例子就是java.util.HashMap里的Node类,用来存储HashMap的键值对:

// 来自java.util.HashMap的核心实现
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;

    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }

    // 省略getKey、getValue、equals等核心方法
}

为什么这么用?
Node只负责存储键值对的核心数据,不需要访问HashMap的非静态成员(比如size、modCount这些实例变量)。静态嵌套类不会持有外部类的引用,更节省内存,同时把Node的实现完全封装在HashMap内部,对外隐藏底层细节,符合面向对象的封装原则。

2. 成员内部类(Member Inner Class)

java.util.ArrayList的迭代器Itr就是典型的成员内部类:

// 来自java.util.ArrayList的迭代器实现
private class Itr implements Iterator<E> {
    int cursor;       // 下一个要返回的元素的索引
    int lastRet = -1; // 上一个返回的元素的索引
    int expectedModCount = modCount;

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

    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        // 直接访问外部类的非静态成员elementData
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }

    // 省略remove、forEachRemaining等方法
}

为什么这么用?
迭代器需要直接访问ArrayList的非静态成员(比如存储元素的elementData数组、集合大小size、修改计数器modCount),成员内部类可以直接引用外部类的实例变量,不需要额外传参。同时把迭代器的实现隐藏在ArrayList内部,对外只暴露Iterator接口,简化了API的复杂度。

3. 局部类(Local Class)

java.util.Collections的checkedCollection方法里就定义了一个局部类,用来给集合做类型校验:

// 来自java.util.Collections的工具方法
public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type) {
    // 局部类:只在这个方法内部使用,对外完全不可见
    class CheckedCollection implements Collection<E>, Serializable {
        private static final long serialVersionUID = 1578914078182001775L;

        final Collection<E> c;
        final Class<E> type;

        CheckedCollection(Collection<E> c, Class<E> type) {
            this.c = Objects.requireNonNull(c);
            this.type = Objects.requireNonNull(type);
        }

        public int size() { return c.size(); }
        public boolean isEmpty() { return c.isEmpty(); }
        // 所有添加元素的方法都会先做类型检查
        public boolean add(E e) {
            type.cast(e); // 校验元素类型,不符合会抛出ClassCastException
            return c.add(e);
        }
        // 省略其他方法
    }
    return new CheckedCollection(c, type);
}

为什么这么用?
这个CheckedCollection类只在checkedCollection方法内部有用,不需要对外暴露。用局部类可以把类型校验的逻辑封装起来,同时不会污染外部的命名空间,而且可以直接访问方法的参数c和type,非常方便。

4. 匿名类(Anonymous Class)

匿名类在JDK里随处可见,比如java.util.Collections的reverseOrder方法,用来生成一个反转顺序的比较器:

// 来自java.util.Collections
public static <T> Comparator<T> reverseOrder() {
    return new Comparator<T>() {
        public int compare(T o1, T o2) {
            return ((Comparable<T>)o2).compareTo(o1);
        }
    };
}

再比如AWT/Swing里的事件监听(JRE GUI场景):

// 来自JRE的AWT事件处理示例
Button submitBtn = new Button("提交");
submitBtn.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("按钮被点击了!");
    }
});

为什么这么用?
匿名类适合只需要使用一次的场景,比如临时的比较器、事件监听器。不需要单独定义一个类,简化了代码结构,而且可以直接访问外部方法的局部变量(只要是final或者Java 8+里的effectively final变量)。

这些案例都是JDK/JRE源码里的真实实现,理解它们的使用场景,比死记硬背内部类的语法规则有用多了!

内容的提问来源于stack exchange,提问作者koniga-ganica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:41:37