Iterable接口下的forEach()方法可以用来遍历集合内的元素,示例如下:
import java.util.*;
public class Test {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add(10);
list.add(6);
list.add(11);
list.add(1);
list.add(20);
System.out.println("使用List的foreach方法遍历List");
list.forEach(System.out::println);
}
}
Arrays工具类下的asList()方法可以将数组转换成List集合,尝试使用Arrays.asList(数组).foreach()来遍历数组。
1.被转换的数组是基本数据类型的数组(以int[]为例)
import java.util.*;
public class Test {
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
Arrays.asList(array).forEach(System.out::println);
}
}
2.被转换的数组是引用类型的数组(以String[]为例)
import java.util.*;
public class Test {
public static void main(String[] args) {
String[] array = {"aaa","bbb","ccc","ddd","eee"};
Arrays.asList(array).forEach(System.out::println);
}
}
总结上述运行结果发现:基本数据类型的数组通过Arrays.asList()转换为List集合后遍历返回的是一个数组的地址值。引用数据类型通过这种方式转换为List集合后才能够遍历其中的元素。
补充:而且基本数据类型数组的结果就是原数组的地址
查看Arrays.asList()的源码:Arrays.asList()方法会创建一个Arrays的内部类ArrayList并返回(返回的集合类型是java.util.Arrays.ArrayList,并不是我们常用的java.util.ArrayList,但是这不重要),可以看到这个方法将传入的参数解析成为数组并赋值给内部类ArrayList的成员变量a[]。
Arrays.asList()方法的参数是一个泛型的可变长参数T...a。
可变长参数的形参用来表示可以传入任意个指定类型的实参(0个、1个、任意个,也可以传入一个数组)Java编译器会根据实参数量创建一个指定类型的数组,如指定可变长参数为String...类型,数组类型为String[],指定可变长参数为int...类型,数组类型为int[]。当不如参数时,Java编译器会创建一个空数组,而不是传入参数null。
可变长参数示例:
public class Test {
public static void variableLengthParameterTest(String... strs) {
if(strs.length == 0){
System.out.println("没有输入参数");
}else{
for(String str : strs){
System.out.println(str);
}
}
}
public static void main(String[] args) {
String strs[] = {"aaa","bbb","ccc","ddd","eee"};
System.out.println("不输入参数");
variableLengthParameterTest();
System.out.println("输入一个参数");
variableLengthParameterTest("aaa");
System.out.println("输入三个参数");
variableLengthParameterTest("aaa","bbb","ccc");
System.out.println("输入一个数组");
variableLengthParameterTest(strs);
}
}
泛型的本质是参数化类型,即给类型指定一个参数,然后在使用时再指定此参数具体的值,那样这个类型就可以在使用时决定了。这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
泛型有一个重要的机制——类型擦除。Java编译器在执行泛型擦除之后类型会被改变为Object类型,所以泛型只能使用引用数据类型!!!!!
验证泛型机制是引用数据类型:
import java.lang.reflect.Method;
class inner{
public T test(T param){
return param;
}
}
public class Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException{
Class clazz = inner.class;
Method[] methods = clazz.getMethods();
for(Method method : methods){
System.out.println(method.getReturnType() + "\t" + method.getName());
}
}
}
可以看到代码中指定的返回类型是泛型T,使用反射机制获取到的返回类型是java.lang.Object。
使用Arrays.asList()方法是所需要的参数是一个引用类型的可变长参数,当传入一个引用类型的数组(如new Stirng[]{"aaa","bbb","ccc"})时由于数组内的元素都是引用类型的所以Java编译器会创建一个new Stirng[]{"aaa","bbb","ccc"}数组并传入;当传入一个基本数据类型的数组(如new int[]{1,2,3})时由于其内部元素不是引用类型,而其本身是一个引用类型,Java编译器会创建一个int[][]数组(二维数组,可以看作一个内部元素都是一维数组的一维数组),并将我们传入的数组{1,2,3}存入这个二维数组,返回的ArrayList内部成员数组a={{1,2,3}}。所以在使用Arrays.asList(new int{1,2,3}).forEach()遍历时会打印出传入数组的地址。
关于内部类Arrays.ArrayList的forEach()方法:先判断成员变量数组a是否为空,如果为空则抛出空指针异常NullPointerException,否则遍历数组a并执行传入的方法。