为什么Arrays.asList(1, 2)不用真正的ArrayList而用内部类呢

zhidiantech · · 24 次点击 · · 开始浏览    
`Arrays.asList` 方法返回的并不是 `java.util.ArrayList`,而是一个由 `Arrays` 类内部定义的静态类 `ArrayList`。这个内部类实现了 `List` 接口,并且提供了一些优化以提高性能和减少内存占用。以下是几个关键原因解释为什么 `Arrays.asList` 使用内部类而不是 `java.util.ArrayList`: ### 1. **固定大小的列表** - **不可变性**:`Arrays.asList` 返回的列表是固定大小的。这意味着你不能通过 `add`, `remove` 等方法改变列表的大小。这种设计符合 `Arrays.asList` 的预期用途——将数组转换为一个列表视图。 - **内部类的设计**:为了实现这种固定大小的行为,`Arrays` 类定义了一个内部类 `ArrayList`,它重写了 `add`, `remove` 等方法来抛出 `UnsupportedOperationException` 异常,从而防止对列表进行修改。 ### 2. **性能优化** - **直接包装数组**:`Arrays.asList` 内部类并没有创建一个新的数组或复制原有的数组数据,而是直接使用了传入的数组作为其底层存储。这种方式避免了不必要的内存分配和数据复制,提高了性能。 - **轻量级实现**:由于它只是对现有数组的一个视图,因此不需要像 `java.util.ArrayList` 那样管理动态增长的内部数组。这使得它的实现更加简单和高效。 ### 3. **节省内存** - **共享数据结构**:由于 `Arrays.asList` 返回的列表直接引用了传入的数组,因此不需要额外的内存来存储相同的数据。这对于处理大型数组特别有利,因为它减少了内存占用。 ### 4. **行为一致性** - **保持数组特性**:`Arrays.asList` 返回的列表仍然保留了数组的一些特性,例如固定大小。如果你希望得到一个可以动态修改的列表,你需要显式地将其转换为 `java.util.ArrayList` 或其他可变的列表类型: ```java List<Integer> mutableList = new ArrayList<>(Arrays.asList(1, 2)); ``` ### 示例代码 以下是一个简单的示例,展示了 `Arrays.asList` 的行为: ```java import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { // 创建一个固定大小的列表 List<Integer> fixedSizeList = Arrays.asList(1, 2); System.out.println(fixedSizeList); // 输出: [1, 2] // 尝试添加元素会抛出 UnsupportedOperationException try { fixedSizeList.add(3); } catch (UnsupportedOperationException e) { System.out.println("Cannot add to a fixed-size list"); } // 如果需要一个可变的列表,可以这样做 List<Integer> mutableList = new ArrayList<>(fixedSizeList); mutableList.add(3); System.out.println(mutableList); // 输出: [1, 2, 3] } } ``` ### 内部类 `ArrayList` 的实现细节 以下是 `Arrays` 类中 `ArrayList` 内部类的部分实现(简化版): ```java private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { private final E[] a; ArrayList(E[] array) { if (array == null) throw new NullPointerException(); a = array; } public int size() { return a.length; } public Object[] toArray() { return a.clone(); } public E get(int index) { return a[index]; } public E set(int index, E element) { E oldValue = a[index]; a[index] = element; return oldValue; } public void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); } } ``` ### 总结 `Arrays.asList` 使用内部类 `ArrayList` 而不是 `java.util.ArrayList` 主要是为了实现固定大小的列表视图,同时提供性能优化和节省内存。这种方法非常适合于那些只需要读取或修改现有数组内容而不改变其大小的场景。如果需要一个可变的列表,则需要手动将其转换为 `java.util.ArrayList` 或其他合适的列表类型。
24 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传