假如我们需要用到1000个相同类型的数据,肯定不可能创建1000个变量,
这样既不方便,也不直观,也不便于我们使用。这时就需要用到数组。
一、数组的声明与使用
1 public class Array { 2 public static void main(String[] args) { 3 int a[] = null; //数据类型 数组名 = null;声明一维数组 4 a = new int[10]; //数组名 = new 数据类型[长度];分配内存给数组。 5 } 6 7 }
首先第一句,声明了数组a,此时栈内存中就分配了一块内存空间给a,此时将null给a代表不指向任何实例(此时a只在栈内存中进行了创建,但是它没有指向堆内存中任何对象实例,也没有指向堆内存),所以不能使用(引用)具体的实例数据。
第二句,用new在堆内存中创建了十个int类型的存储空间,然后把这个内存空间的地址给a。
此时堆内存中就可以存放10个int型的数据,栈内存中的a存放了堆内存的地址值。这时可以通过数组a引用堆内存的内容。
二、数组元素的表示方法
数组用下标区别元素,下标从0到n-1;
例如创建的a数组长度为10,即下标从0~ 9;
a[10] 并不存在,引用a[10]会出现错误,下标只能到a[9];
public class Array { public static void main(String[] args) { int a[] = null; a = new int[10]; for(int i = 0; i < 10; i++){ //其中i < 10可以写成 i<a.length, a[i] = i; //数组循环赋值并打印 System.out.println(a[i]); } System.out.println(a.length); //数组名.length代表数组的长度,且会返回一个int值。 } }
运行结果: 0 1 2 3 4 5 6 7 8 910
三、数组的静态初始化
上面给数组赋值是在数组创建完毕后,再给数组中元素赋值,属于动态初始化。
在数组元素创建时就直接赋值属于静态初始化。
数据类型 数组名[] = {初始值0,初始值1,初始值2,···,初始值 n};
虽然声明时没有指定数组长度,但由初始化时初始值的个数编译器会自动确定长度和初始值个数相同。
1 public class Array { 2 public static void main(String[] args) { 3 int a[] = {0,1,2,3,4,5,6,7,8,9}; 4 for(int i = 0; i < a.length; i++){ 5 a[i] = i; 6 System.out.println(a[i]); 7 } 8 System.out.println(a.length); 9 } 10 }
运行结果: 0 1 2 3 4 5 6 7 8 9 10
三、二维数组
一维数组可以看做是具有1行n列的元素的集合。
而二维数组可以看做是具有m行n列的元素的集合。
声明方法和一维类似,不同的是需要确定行数和列数。
1 public class Array { 2 public static void main(String[] args) { 3 int a[][] = new int[3][4]; //代表创建了一个三行四列的数组。 4 } 5 }
二维数组的引用
public class Array { public static void main(String[] args) { int a[][] = new int[3][4]; int num = 0; for(int i = 0; i <a.length; i++){ for(int j = 0; j < a[i].length; j++){ a[i][j] = num++; System.out.print(a[i][j] + " " );//前面的下标代表行,后面代表列 } System.out.println(); } } }
运行结果:0 1 2 3 4 5 6 7 8 9 10 11
上列的a.length可以看做组成二维数组的一维数组的个数(例如上面可以看做由三个一维数组组成了二维数组),a[i].length可以看做当前行中数组的个数。
由此推到n维,假设有n维数组A;则a.length代表n维数组中n-1维数组的个数,a[i].length代表n-1维数组中n-2维数组的个数......
二维数组中每一行的元素个数也不一定相等
例如
1 public class Array { 2 public static void main(String[] args) { 3 int a[][] = {{1,},{1,2},{1,2,3}}; 4 int num = 0; 5 for(int i = 0; i <a.length; i++){ 6 for(int j = 0; j < a[i].length; j++){ 7 a[i][j] = num++; 8 System.out.print(a[i][j] + " " );//前面的下标代表行,后面代表列 9 } 10 System.out.println(); 11 } 12 } 13 }
运行结果: 0 1 2 3 4 5
初始化时一共有三个一维数组,但每一行的元素个数不同,a[i].length代表当前行中元素的个数。
我们尝试输出a[0][2]会出现java.lang.ArrayIndexOutOfBoundsException,代表数组下标越界。
说明a[0][2]没有分配内存,也可以说它不存在。
四、数组的引用传递
我们看下列代码
1 public class Array { 2 public static void main(String[] args) { 3 int a[] = {1,2,3}; 4 fun(a); 5 System.out.println(a[0]); 6 } 7 static void fun(int x[]){ 8 x[0] = 123; 9 } 10 }
运行结果: 123
可以发现,我们将数组名a作为参数传递给了fun方法。
fun方法中修改了第一个元素的值,在main中输出的值也改变了了。
说明堆内存中的值被更改了。
传递过程:
首先前面讲到数组名存放的只是堆内存中创建好的数组空间的地址。
将数组名传递给函数fun传递的是堆内存空间的地址。
这时fun中的数组x[]就和main中的数组a[]指向了同一块地址。
利用x[]就可以对堆内存中内容进行操作。
fun方法结束后,数组x[]会被释放掉,但对堆内存的操作却保留了下来。
这点和c语言的指针类似。
五、java对数组的新特性(jdk1.5(javase5.0)之后)。
1.可变参数
在调用一个方法时,会根据定义的传递指定的参数。
而可变参数代表传递给方法的参数个数是不定的。
方法名称(类型...参数名称){
}
public class Array { public static void main(String[] args) { int a[] = new int[5]; fun(); fun(1); fun(1,2,3); fun(1,2,3,4,5); } private static void fun(int...arg){ int i = 0; for(i = 0; i <arg.length; i++){ System.out.print(arg[i]); } System.out.println(); }
运行结果: //此处有一个换行,当 1 123 12345
向方法中传递可变参数后,可变参数是以数组的形式保持下来的,调用可变参数也是以数组得形式调用
上列代码fun方法中可以看做把可变参数传递给了名为arg的数组,arg数组中就存放了传递过来的参数。
2.foreach输出
for(数据类型 变量名称:数组名称){
}
1 public class Array { 2 public static void main(String[] args) { 3 int a[] = new int[10]; 4 for(int i = 0; i < a.length; i++) 5 a[i] = i; 6 for(int m:a){ //用foreach输出,就相当于逐次将数组元素给变量m, 7 System.out.print(m + " "); //然后通过变量m来进行操作。 8 } 9 } 10 }
运行结果: 0 1 2 3 4 5 6 7 8 9
下面结合可变参数和foreach
1 public class Array { 2 public static void main(String[] args) { 3 int a[] = new int[5]; 4 fun(); 5 fun(1); 6 fun(1,2,3); 7 fun(1,2,3,4,5); 8 } 9 10 private static void fun(int...ar){ 11 for(int m : ar){ 12 System.out.print(m); 13 } 14 System.out.println(); 15 } 16 }
运行结果: 1 123 12345
来源:https://www.cnblogs.com/huang-changfan/p/9419237.html