Arrays.asList和Lists.newList使用时的陷阱

 

昨天在开发中遇到一个场景,调用RPC,拿到返回结果(int[]数组),使用jackSon序列化为Json对象时,发现一个诡异的现象,在使用Lists.newArrayList和Arrays.asList将数组转为List时,转出来的对象并不是与原数组对应的一个List,二十一个很诡异的对象。后来研究一下JDK,发现了陷阱所在。

首先看一下Arrays.asList这个方法,这个方法可以将数组转成list,是JDK中java.util包中Arrays类的静态方法。

  1. public class ArraysTest {

  2. private static void asListTest(){

  3. String stringArray[]={"aa","bb","cc"};

  4. List<String> sList= Arrays.asList(stringArray);

  5. for(String str:sList){//能遍历出各个元素

  6. System.out.println(str);

  7. }

  8. System.out.println(sList.size());

  9.  
  10. System.out.println("- - - - - - - - - - -");

  11.  
  12. int intArray[]={11,22,33};

  13. List intList=Arrays.asList(intArray);

  14. for(Object o:intList){//就一个元素

  15. System.out.println(o.toString());

  16. }

  17.  
  18. System.out.println("- - - - - - - - - - -");

  19.  
  20. Integer integerArray[]={11,22,33};

  21. List<Integer> objList=Arrays.asList(integerArray); //数组里的每一个元素都是作为list中的一个元素

  22. for(int a:objList){

  23. System.out.println(a);

  24. }

  25.  
  26. System.out.println("- - - - - - - - - - -");

  27. }

  28.  
  29. public static void main(String[] args){

  30. asListTest();

  31. }

  32. }

结果如下:

  1. Connected to the target VM, address: '127.0.0.1:12064', transport: 'socket'

  2. aa

  3. bb

  4. cc

  5. 3

  6. - - - - - - - - - - -

  7. [I@2db0f6b2

  8. - - - - - - - - - - -

  9. 11

  10. 22

  11. 33

  12. - - - - - - - - - - -

  13. Disconnected from the target VM, address: '127.0.0.1:12064', transport: 'socket'

  14.  
  15. Process finished with exit code 0

当基本类型数组使用Arrays.asList方法转List时,并不能转成正常的List,随后我看了一下jdk源码,看到问题所在

  1. public static <T> List<T> asList(T... a) {

  2. return new ArrayList<>(a);

  3. }

  4.  
  5. private static class ArrayList<E> extends AbstractList<E>

  6. implements RandomAccess, java.io.Serializable

  7. {

  8. private static final long serialVersionUID = -2764017481108945198L;

  9. private final E[] a;

  10.  
  11. ArrayList(E[] array) {

  12. a = Objects.requireNonNull(array);

  13. }

  14. }

基本类型int不是对象类型,在使用Arrays.asList时,做泛型擦除时,将int[]当做对象类型,所以转成一个只有一个元素的List。在使用Arrays.asList转成的List时同样要注意,Arrays.asList返回类型为Arrays类内部定义的私有类ArrayList,并且继承与AbstractList,翻阅AbstractList源码是可以发现,是不支持add和remove操作的,也就是说Arrays.asList返回的List是个固定大小的List。

如果希望转过后的list可以支持add和remove操作,可使用如下方法:

  1. /*方法一*/

  2. ArrayList<Integer> copyArrays=new ArrayList<>(Arrays.asList(integerArray));

  3.  
  4. /*方法二*/

  5. List<Integer> integerList = new ArrayList<>();

  6. Collections.addAll(integerList, integerArray);

如果想把一个基本类型数组转化为List,可使用如下方法:

Arrays.asList(ArrayUtils.toObject(intArray));

在使用com.google.common.collect提供的jar包Lists类的Lists.newArrayList方法时,有相同的问题,如果传入基本类型数组,也无法转化成一个正常的List,这一点跟ArrayList结果是一致的。但是对象数组进行转化时,有一点不同,转成的List是支持add和remove操作的。

猜你喜欢

转载自blog.csdn.net/It_BeeCoder/article/details/90792461