在实际开发过程中我们经常使用 asList 讲数组转换为 List,这个方法使用起来非常方便,但是 asList 方法存在几个缺陷:

一、避免使用基本数据类型数组转换为列表

使用 8 个基本类型数组转换为列表时会存在一个比较有味的缺陷。先看如下程序:


  1. public static void main(String[] args) {
  2. int[] ints = {1,2,3,4,5};
  3. List list = Arrays.asList(ints);
  4. System.out.println("list'size:" + list.size());
  5. }
  6. ------------------------------------
  7. outPut
  8. list'size:1

程序的运行结果并没有像我们预期的那样是 5 而是逆天的 1,这是什么情况?先看源码:


  1. public static <T> List<T> asList(T... a) {
  2. return new ArrayList<>(a);
  3. }

asList 接受的参数是一个泛型的变长参数,我们知道基本数据类型是无法发型化的,也就是说 8 个基本类型是无法作为 asList 的参数的, 要想作为泛型参数就必须使用其所对应的包装类型。但是这个这个实例中为什么没有出错呢?因为该实例是将 int 类型的数组当做其参数,而在 Java 中数组是一个对象,它是可以泛型化的。所以该例子是不会产生错误的。既然例子是将整个 int 类型的数组当做泛型参数,那么经过 asList 转换就只有一个 int 的列表了。如下:


  1. public static void main(String[] args) {
  2. int[] ints = {1,2,3,4,5};
  3. List list = Arrays.asList(ints);
  4. System.out.println("list 的类型:" + list.get(0).getClass());
  5. System.out.println("list.get(0) == ints:" + list.get(0).equals(ints));
  6. }
  7. --------------------------------------------
  8. outPut:
  9. list 的类型:class [I
  10. list.get(0) == intstrue

从这个运行结果我们可以充分证明 list 里面的元素就是 int 数组。弄清楚这点了,那么修改方法也就一目了然了:将 int 改变为 Integer。


  1. public static void main(String[] args) {
  2. Integer[] ints = {1,2,3,4,5};
  3. List list = Arrays.asList(ints);
  4. System.out.println("list'size:" + list.size());
  5. System.out.println("list.get(0) 的类型:" + list.get(0).getClass());
  6. System.out.println("list.get(0) == ints[0]:" + list.get(0).equals(ints[0]));
  7. }
  8. ----------------------------------------
  9. outPut:
  10. list'size:5
  11. list.get(0) 的类型:class java.lang.Integer
  12. list.get(0) == ints[0]:true

Java 细节(2.1):在使用 asList 时不要将基本数据类型当做参数。

二、asList 产生的列表不可操作

对于上面的实例我们再做一个小小的修改:


  1. public static void main(String[] args) {
  2. Integer[] ints = {1,2,3,4,5};
  3. List list = Arrays.asList(ints);
  4. list.add(6);
  5. }

该实例就是讲 ints 通过 asList 转换为 list 类别,然后再通过 add 方法加一个元素,这个实例简单的不能再简单了,但是运行结果呢?打出我们所料:


  1. Exception in thread "main" java.lang.UnsupportedOperationException
  2. at java.util.AbstractList.add(Unknown Source)
  3. at java.util.AbstractList.add(Unknown Source)
  4. at com.chenssy.test.arrayList.AsListTest.main(AsListTest.java:10)

运行结果尽然抛出 UnsupportedOperationException 异常,该异常表示 list 不支持 add 方法。这就让我们郁闷了,list 怎么可能不支持 add 方法呢?难道 JDK 脑袋堵塞了?我们再看 asList 的源码:


  1. public static <T> List<T> asList(T... a) {
  2. return new ArrayList<>(a);
  3. }

asList 接受参数后,直接 new 一个 ArrayList,到这里看应该是没有错误的啊?别急,再往下看:


  1. private static class ArrayList<E> extends AbstractList<E>
  2. implements RandomAccess, java.io.Serializable{
  3. private static final long serialVersionUID = -2764017481108945198L;
  4. private final E[] a;
  5. ArrayList(E[] array) {
  6. if (array==null)
  7. throw new NullPointerException();
  8. a = array;
  9. }
  10. //.................
  11. }

这是 ArrayList 的源码,从这里我们可以看出,此 ArrayList 不是 java.util.ArrayList,他是 Arrays 的内部类。该内部类提供了 size、toArray、get、set、indexOf、contains 方法,而像 add、remove 等改变 list 结果的方法从 AbstractList 父类继承过来,同时这些方法也比较奇葩,它直接抛出 UnsupportedOperationException 异常:


  1. public boolean add(E e) {
  2. add(size(), e);
  3. return true;
  4. }
  5. public E set(int index, E element) {
  6. throw new UnsupportedOperationException();
  7. }
  8. public void add(int index, E element) {
  9. throw new UnsupportedOperationException();
  10. }
  11. public E remove(int index) {
  12. throw new UnsupportedOperationException();
  13. }

通过这些代码可以看出 asList 返回的列表只不过是一个披着 list 的外衣,它并没有 list 的基本特性(变长)。该 list 是一个长度不可变的列表,传入参数的数组有多长,其返回的列表就只能是多长。所以:

from: http://wiki.jikexueyuan.com/project/java-enhancement/java-thirtysix.html

Java 集合细节(二):asList 的缺陷的更多相关文章

  1. Java提高篇(三五)-----Java集合细节(一):请为集合指定初始容量

    集合是我们在Java编程中使用非常广泛的,它就像大海,海纳百川,像万能容器,盛装万物,而且这个大海,万能容器还可以无限变大(如果条件允许).当这个海.容器的量变得非常大的时候,它的初始容量就会显得很重 ...

  2. (Set, Map, Collections工具类)JAVA集合框架二

    Java集合框架部分细节总结二 Set 实现类:HashSet,TreeSet HashSet 基于HashCode计算元素存放位置,当计算得出哈希码相同时,会调用equals判断是否相同,相同则拒绝 ...

  3. 【由浅入深理解java集合】(二)——集合 Set

    上一篇文章介绍了Set集合的通用知识.Set集合中包含了三个比较重要的实现类:HashSet.TreeSet和EnumSet.本篇文章将重点介绍这三个类. 一.HashSet类 HashSet简介 H ...

  4. java 集合框架(二)Iterable接口

    Iterable接口是java 集合框架的顶级接口,实现此接口使集合对象可以通过迭代器遍历自身元素,我们可以看下它的成员方法 修饰符和返回值 方法名 描述 Iterator<T> iter ...

  5. Java集合系列(二):ArrayList、LinkedList、Vector的使用方法及区别

    本篇博客主要讲解List接口的三个实现类ArrayList.LinkedList.Vector的使用方法以及三者之间的区别. 1. ArrayList使用 ArrayList是List接口最常用的实现 ...

  6. Java提高篇(三六)-----Java集合细节(二):asList的缺陷

    在实际开发过程中我们经常使用asList讲数组转换为List,这个方法使用起来非常方便,但是asList方法存在几个缺陷: 一.避免使用基本数据类型数组转换为列表 使用8个基本类型数组转换为列表时会存 ...

  7. Java提高配(三七)-----Java集合细节(三):subList的缺陷

    我们经常使用subString方法来对String对象进行分割处理,同时我们也可以使用subList.subMap.subSet来对List.Map.Set进行分割处理,但是这个分割存在某些瑕疵. 一 ...

  8. [知识整理]Java集合(二) - Set

    一.实现Set的几个类 HashSet.LinkedHashSet.TreeSet.ConcurrentSkipListSet.CopyOnWriterArraySet 二.对应底层的数据结构 Has ...

  9. Java提高篇(三八)-----Java集合细节(四):保持compareTo和equals同步

    在Java中我们常使用Comparable接口来实现排序,其中compareTo是实现该接口方法.我们知道compareTo返回0表示两个对象相等,返回正数表示大于,返回负数表示小于.同时我们也知道e ...

随机推荐

  1. 优雅的vue.js

    优雅的vue.js代码 https://www.cnblogs.com/zhengrunlin/p/9164951.html watch 与 computed 的巧妙结合 如上图,一个简单的列表页面. ...

  2. Spark中hashshuffle与sortshuffle

    在spark1.2以上的版本中,默认shuffle的方式已经变成了sortshuffle(在spark.shuffle.manager修改org.apache.spark.shuffle.sort.H ...

  3. JdbcTemplate使用小结

    org.springframework.jdbc.core.JdbcTemplate.query(String sql, Object[] args, RowMapper<StaffUnionV ...

  4. 膨胀卷积与IDCNN

    Dilation 卷积,也被称为:空洞卷积.膨胀卷积. 一.一般的卷积操作: 首先,可以通过动态图,理解正常卷积的过程: 如上图,可以看到卷积操作. 对于CNN结构,通常包括如下部分: 输入层 (in ...

  5. Android Native层异步消息处理框架

     *本文系作者工作学习总结,尚有不完善及理解不恰当之处,欢迎批评指正* 一.前言 在NuPlayer中,可以发现许多类似于下面的代码: //============================== ...

  6. 2010-2011 ACM-ICPC, NEERC, Moscow Subregional Contest Problem I. Interest Targeting 模拟题

    Problem I. Interest Targeting 题目连接: http://codeforces.com/gym/100714 Description A unique display ad ...

  7. Maven入门指南② :Maven 常用命令,手动创建第一个 Maven 项目

    1.根据 Maven 的约定,我们在D盘根目录手动创建如下目录及文件结构: 2.打开pom.xml文件,添加如下内容: <project xmlns="http://maven.apa ...

  8. DIV+javascript实现首尾相连循环滚动效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. 群晖NAS简介(转)

    Synology 群晖科技(Synology )创立于 2000 年,自始便专注于打造高效能.可靠.功能丰富且绿色环保的 NAS 服务器,是全球少数几家以单纯的提供网络存储解决方案获得世界认同的华人企 ...

  10. div光标

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...