【Java 开发常见的坑】—— Arrays 使用

【Java 开发常见的坑】—— Arrays 使用

日常开发中,Arrays工具类十分常用,但如果对Arrays的源码不熟悉的话,就有可能踩到坑。

以下是我日常开发或身边同事遇到关于Arrays工具类的坑:

使用Arrays.asList转换为List数组,并对原始的对象修改

使用Arrays.asList转换为List数组,并对List数组进行增删改操作

使用Arrays.asList转换基本类型对象

踩坑1.使用Arrays.asList转换为List数组,并对原始的对象修改

实例:

public class JavaTestApplication {

public static void main(String[] args) {

// 原始数组对象

String[] strArray = {"H", "e", "l", "l", "o"};

List stringList = Arrays.asList(strArray);

System.out.println(stringList);

strArray[0] = "666";

System.out.println(stringList);

}

}

输出结果:

[H, e, l, l, o]

[666, e, l, l, o]

可以发现,使用Arrays.asList将原来的数组对象转换为list对象后,改变原来的数组对象,list对象也会一同的修改!

深入源码一探究竟!

public static List asList(T... a) {

return new ArrayList<>(a);

}

嗯?怎么和我平常使用new ArrayList()创建对象不太一样?比如平常创建ArrayList对象的时候,一般都是通过new ArrayList()或new ArrayList(Collection c),但使用Arrays.asList转换的时候,参数却是一个数组对象,而不是集合类型。莫非是Arrays类的ArrayList对象和java.util.ArrayList不一样?

打开 Arrays.asList 方法中的 ArrayList 对象,居然是Arrays内的内部类!

private static class ArrayList extends AbstractList implements RandomAccess, java.io.Serializable {

private static final long serialVersionUID = -2764017481108945198L;

private final E[] a;

// 直接将参数的数组对象赋值给Arrays.ArrayList的对象

ArrayList(E[] array) {

a = Objects.requireNonNull(array);

}

// 先省略其他方法

}

通过源码终于知道示例中为什么修改原始的数组会影响转换后的List对象,因为都是共享同一个数组对象呀(也就是说共享同一块内存)!

既然知道问题所在,那就容易解决啦!

public class JavaTestApplication {

public static void main(String[] args) {

String[] strArray = {"H", "e", "l", "l", "o"};

List stringList = new ArrayList(Arrays.asList(strArray));

System.out.println(stringList);

strArray[0] = "666";

System.out.println(stringList);

}

}

输出结果:

[H, e, l, l, o]

[H, e, l, l, o]

结果是达到预想的情况,其实就是通过new一个ArrayList对象,新建一个ArrayList对象的话,就不会共享同一块内存啦!

踩坑2.使用Arrays.asList转换为List数组,并对List数组进行增删改操作

那现在的使用场景,如果我只需要通过Arrays.asList转换为List集合后,对转换后的集合进行增删改操作,那下面的代码会由问题吗?

public class JavaTestApplication {

public static void main(String[] args) {

String[] strArray = {"H", "e", "l", "l", "o"};

List stringList = Arrays.asList(strArray);

System.out.println(stringList);

stringList.add("666");

System.out.println(stringList);

}

}

输出结果:

[H, e, l, l, o]

Exception in thread "main" java.lang.UnsupportedOperationException

at java.util.AbstractList.add(AbstractList.java:148)

at java.util.AbstractList.add(AbstractList.java:108)

at com.muggle.javatest.JavaTestApplication.main(JavaTestApplication.java:12)

哦豁!又有问题!由第一个"坑"可知,asList返回的ArrayList实际上是Arrays的内部类,而内部类ArrayList继承AbstractList抽象类,实际上,示例中的add方法调用的是抽象类AbstractList的add方法,这是一个默认实现方法

public abstract class AbstractList extends AbstractCollection implements List {

public boolean add(E e) {

add(size(), e);

return true;

}

public void add(int index, E element) {

throw new UnsupportedOperationException();

}

}

解决的办法其实和上面一样,将asList返回的ArrayList通过new ArrayList()新建一个java.util.ArrayList对象就行了

public class JavaTestApplication {

public static void main(String[] args) {

String[] strArray = {"H", "e", "l", "l", "o"};

List stringList = new ArrayList(Arrays.asList(strArray));

System.out.println(stringList);

stringList.add("666");

System.out.println(stringList);

}

}

踩坑3.使用Arrays.asList转换基本类型对象

如果数组是基本数据类型的呢?使用Arrays.asList会不会有问题?

public class JavaTestApplication {

public static void main(String[] args) {

int[] intArray = {1,2,3,4,5,6};

List list = Arrays.asList(intArray);

System.out.println(list);

System.out.println(list.size());

list.stream().forEach(x-> System.out.println(x.getClass()));

}

}

输出结果:

[[I@3feba861]

1

class [I

从输出结果可得知,int[]数组转换为List对象后,长度只有1,类型是整型数组。因此,通过上述的使用是无法将基本数据类型的数组转换为List对象。

有两种办法,第一种方法就是通过将基本类型数组转换为IntStream流再转换为List集合;第二种方法是将基本数据类型改为对应的包装类类型

public class JavaTestApplication {

public static void main(String[] args) {

int[] intArray = {1, 2, 3, 4, 5, 6};

// 方法1:将int数组转换为IntStream流,并且调用boxed方法将stream流内的元素都以整型存在

List intStreamList = Arrays.stream(intArray).boxed().collect(Collectors.toList());

intStreamList.stream().forEach(x -> System.out.print(x + " "));

// 方法2:将int数组改为Integer类型

Integer[] integerArray = {1, 2, 3, 4, 5, 6};

List integerList = Arrays.asList(integerArray);

integerList.stream().forEach(x -> System.out.print(x + " "));

}

}

以上都是常见的Arrays使用不正确的场景,希望能够诸位在开发的时候,多加注意!

如果觉得文章不错的话,麻烦点个赞哈,你的鼓励就是我的动力!对于文章有哪里不清楚或者有误的地方,欢迎在评论区留言~

参考资料:

极客时间专栏:Java业务开发常见错误100例

相关推荐

形容涟漪的成语有哪些(描写涟漪的成语)
365bet亚洲官网网址

形容涟漪的成语有哪些(描写涟漪的成语)

🗓️ 08-30 👁️ 7191
[隐私浏览器终极指南] 2025年最佳“翻墙”浏览器深度评测:Firefox vs. Chrome
支付宝扫福入口
365bet亚洲官网网址

支付宝扫福入口

🗓️ 08-21 👁️ 6864
天海翼 个人图片
365bet亚洲官网网址

天海翼 个人图片

🗓️ 09-05 👁️ 581
觇字的意思
365bet官方下载

觇字的意思

🗓️ 06-29 👁️ 152
你怕鬼吗?解读恐惧——人类生存的本能反应
手机bt365

你怕鬼吗?解读恐惧——人类生存的本能反应

🗓️ 06-29 👁️ 6555