java类型、泛型、可变参数
先说一个小问题,google的guava是一个不错的工具包,guava包内的Lists工具类的newArrayList像下面的这样使用为什么会报“Type mismatch: cannot convert from ArrayList<int[]> to List
int array[] = {1, 2, 3, 4, 5};
List<Integer> list = Lists.newArrayList(array);
要回答这个问题,我们先来看看newArrayList的定义:
com.google.common.collect.Lists.newArrayList(E...)
newArrayList是一个参数数量可变的方法,其中E表示泛型,你像下面这样使用都是没有问题的:
//使用方法一
List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);
//使用方法二
int a = 1, b = 2, c = 3, d = 4, e = 5;
List<Integer> list = Lists.newArrayList(a, b, c, d, e);
//使用方法三
Integer array[] = {1, 2, 3, 4, 5};
List<Integer> list = Lists.newArrayList(array);
方法三和最开始报错的代码有什么区别呢?只是把int换成Integer就可以,用int就不行呢?
- 泛形要求能包容的是对象类型。
- 可变参数方法,编译器会把最后一个形参转化为一个数组形参。
- 可变参数是兼容数组类参数的。
- 基本类型在java里不属于对象,但数组(包括基本类型的数组)是对象。
- 基本类型都有其各自的包装类型,自动装箱和自动拆箱只针对基本类型。
上文的代码中,“使用方法一”和“使用方法二”会自动装箱,最后都能转化为Integer类型的数组形参;“使用方法三”中本身就是Integer类型的数组,可变参数是兼容数组类参数;对于最开始报错的那个代码,由于int类型的数组是一个对象,不能对对象进行自动装箱,可变参数方法Lists.newArrayList会把int类型的数组array当成一个参数看待,而不是数组的元素数量个参数。
集合与数组相互转换
数组和集合都是我们日常编码中经常用到的数据类型,如果给你一个集合,你会怎么样变成数组呢?给你一个数组,你会怎么把它变成集合呢?
方法一:遍历法
//数组变集合
int array[] = {1, 2, 3, 4, 5};
List<Integer> list = new ArrayList<Integer>(array.length);
for(int i = 0; i < array.length; i++){
list.add(array[i]);
}
//集合变数组
List<Integer> list = initList();
Integer[] array = new Integer[list.size()];
for(int i = 0; i < list.size(); i++){
array[i] = list.get(i);
}
方法二:使用第三方工具类或JDK自带工具类
//集合转数组
Collection<Integer> collection = initCollection();
Integer[] array = collection.toArray(new Integer[collection.size()]);
//数组转集合,利用guava的Lists,Sets等工具类
com.google.common.collect.Lists.newArrayList(E...)
org.assertj.core.util.Sets.newLinkedHashSet(T...)
org.assertj.core.util.Sets.newTreeSet(T...)
常用方法二,方法一不用。