适配器模式的核心目标是解决接口不匹配的问题,通过引入一个中间层,将源对象的接口转换为目标接口期望的形式,让原本无法一起工作的类可以正常协作。在Java标准库中,Arrays.asList方法就是适配器模式的经典实践,它完成了数组到List接口的适配工作。

适配器模式的核心结构
适配器模式通常包含三个核心角色:
- 目标接口(Target):客户端期望使用的接口,这里是
List接口。 - 适配者(Adaptee):需要被适配的原始对象,这里是普通的数组对象。
- 适配器(Adapter):实现目标接口,同时持有适配者的引用,完成接口转换逻辑,这里就是
Arrays.asList返回的ArrayList内部类。
Arrays.asList的适配实现分析
首先看Arrays.asList的源码实现,它返回的是一个ArrayList实例,但这个ArrayList并不是我们常用的java.util.ArrayList,而是Arrays类的内部私有静态类:
// Arrays类中的asList方法源码
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
// Arrays内部静态私有类ArrayList的定义
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable {
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
@Override
public int size() {
return a.length;
}
@Override
public E get(int index) {
return a[index];
}
@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
// 注意:没有重写add和remove方法,因此调用会抛异常
}
从源码可以看出,这个内部ArrayList类就是适配器角色:
- 它实现了
List接口(目标接口),因此可以被当作List使用。 - 它内部持有原始数组
a(适配者),所有List接口的方法实现都是基于这个数组完成的。
具体适配逻辑拆解
我们对比数组的原有操作和List接口的方法,看适配是如何完成的:
| 数组原有操作 | List接口对应方法 | 适配实现逻辑 |
|---|---|---|
获取数组长度arr.length | size() | 返回内部数组a.length |
通过下标获取元素arr[index] | get(int index) | 返回a[index] |
通过下标修改元素arr[index] = value | set(int index, E element) | 执行a[index] = element并返回旧值 |
| 数组不支持动态添加元素 | add(E e) | 未重写父类AbstractList的默认实现,调用会抛UnsupportedOperationException |
| 数组不支持动态删除元素 | remove(int index) | 未重写父类AbstractList的默认实现,调用会抛UnsupportedOperationException |
适配过程的注意事项
使用Arrays.asList进行适配时,有几个特性需要开发者注意:
- 返回的
List底层绑定的是原始数组,修改List中的元素会同步修改原始数组,反之亦然:
public class Test {
public static void main(String[] args) {
Integer[] arr = {1, 2, 3};
List<Integer> list = Arrays.asList(arr);
// 修改list的元素
list.set(0, 10);
System.out.println(arr[0]); // 输出10,原始数组被修改
// 修改原始数组的元素
arr[1] = 20;
System.out.println(list.get(1)); // 输出20,list同步变化
}
}
- 该
List不支持动态扩容,因此不能调用add、remove等方法,否则会抛出异常:
public class Test {
public static void main(String[] args) {
Integer[] arr = {1, 2, 3};
List<Integer> list = Arrays.asList(arr);
list.add(4); // 运行时抛出UnsupportedOperationException
}
}
- 如果传入的是基本类型数组,比如
int[],会被当作一个单个元素处理,因为泛型不支持基本类型:
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
List<int[]> list = Arrays.asList(arr);
System.out.println(list.size()); // 输出1,整个数组被当作一个元素
}
}
适配器模式在该场景的价值
如果没有Arrays.asList这个适配器,开发者想要把数组当作List使用,就需要手动编写包装类,实现List接口的所有方法,还要处理数组和List之间的数据同步,成本很高。而JDK通过适配器模式封装了这个逻辑,让开发者只需要一行代码就能完成适配,极大降低了使用成本,也体现了设计模式在实际开发中的实用价值。
适配器模式Arrays.asList数组List接口Java修改时间:2026-06-23 18:03:47