我们来回忆一下,C语言中的数组是用来做什么的,没错,在C语言中数组的主要的作用就是用来批量创建变量的,必须是相同类型的。
数组的创建
基本语法如下:
数据类型[] 数组名称 = new 数据类型[]{初始化数据};
数据类型[] 数组名称 = {初始化数据};
下面看代码示例:
int[] arr1 = new int[]{1, 3, 5, 7, 9};
int[] arr2 = {1, 3, 5, 7, 9};
// 也可以沿用C语言的写法,但是不推荐使用
int arr[] = {1, 3, 5, 7, 9};
注意:
new int[]{};
这个语句指定了初始化数据就不能再指定数组长度;指定了数组长度就不能再指定初始化数据。- 这里数组的类型和C语言是不同的,如上面的
int arr[] = {1, 3, 5, 7, 9};
在C语言中arr的类型为int[5],而在Java中arr的类型为int[]。
数组的动态初始化和静态初始化:
Java中数组的静态和动态初始化是相对于程序运行而言的,静态是在程序编译时就初始化好了,动态初始化时再程序运行时才动态分配内存空间。对于代码而言,其实都可以。
下面来看代码示例:
// 静态初始化
int[] arr1 = {1, 3, 5, 7, 9};
// 动态初始化
int[] arr2 = new int[]{1, 3, 5, 7, 9};
数组的使用
获取数组的长度:
public class Test {
public static void main(String[] args) {
int[] arr = {
1, 3, 5, 7, 9,
2, 4, 6, 8, 0
};
// 获取数组长度
System.out.println("arr length: " + arr.length);
}
}
数组中元素的访问和修改:
public class Test {
public static void main(String[] args) {
int[] arr = {
1, 3, 5, 7, 9,
2, 4, 6, 8, 0
};
System.out.println("arr[0]: " + arr[0]);
System.out.println("arr[5]: " + arr[5]);
// 修改下标为9的元素的值
arr[9] = 900;
System.out.println("arr[9]: " + arr[9]);
}
}
下标越界会怎么样?
public class Test {
public static void main(String[] args) {
int[] arr = {
1, 3, 5, 7, 9,
2, 4, 6, 8, 0
};
// 下标访问越界
System.out.println("arr[9]: " + arr[20]);
}
}
从运行结果可以看出,下标访问越界会抛出一个ArrayIndexOutOfBoundsException的异常。
数组的遍历:
public class Test {
public static void main(String[] args) {
int[] arr = {
1, 3, 5, 7, 9,
2, 4, 6, 8, 0
};
// 遍历数组
for (int i = 0; i < arr.length; ++i) {
System.out.print(arr[i] + " ");
}
}
}
使用for-each遍历数组:
public class Test {
public static void main(String[] args) {
int[] arr = {
1, 3, 5, 7, 9,
2, 4, 6, 8, 0
};
// 遍历数组
for (int e : arr) {
System.out.print(e + " ");
}
}
}
数组作为方法的参数
打印数组内容:
public class Test {
public static void main(String[] args) {
int[] arr = {
1, 3, 5, 7, 9,
2, 4, 6, 8, 0
};
arrDisplay(arr);
}
private static void arrDisplay(int[] arr) {
for (int e : arr) {
System.out.print(e + " ");
}
}
}
我们知道,Java中基本类型数据的参数传递,都是传值,其他类型都是传引用,那什么是引用呢?
- 我们可以将引用理解为低配版指针。
下面我们来看个例子:
public class Test {
public static void main(String[] args) {
int num = 10;
func(num);
System.out.println("num = " + num);
}
private static void func(int n) {
n = 20;
System.out.println("n = " + n);
}
}
从上述运行结果可以看出,对形参的修改不会影响到实参。
下面,我们试试传一个引用进去,看看能不能修改数组中的内容:
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2};
func(arr);
System.out.println("arr[0] = " + arr[0]);
}
private static void func(int[] n) {
n[0] = 100;
}
}
我们发现,引用传递可以对引用的数据进行修改。
总结:所谓的引用本质上就是存了一个地址。Java将数组设定成引用类型,这样的话后序进行数组参数传参,其实只是将数组的地址传入到函数形参中。这样就可以避免对整个数组的拷贝(数组可能比较长,那么拷贝开销就会很大)。
数组作为方法的返回值
我们直接来看一个例子来体会:将数组中的每个元素都*2。
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2};
int[] result = transform(arr);
for (int e : result) {
System.out.print(e + " ");
}
}
private static int[] transform(int[] arr) {
int[] ret = new int[arr.length];
for (int i = 0; i < arr.length; ++i) {
ret[i] = arr[i] * 2;
}
return ret;
}
}
数组转字符串
循环遍历打印数组太麻烦,有没有什么办法可以简单的打印数组呢?当然有,Java中提供了数组转字符串的方法。
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {
1, 3, 5, 7, 9,
2, 4, 6, 8, 0
};
System.out.println(Arrays.toString(arr));
}
}
我们自己来实现一下这个接口:
public class Test {
public static void main(String[] args) {
int[] arr = {
1, 3, 5, 7, 9,
2, 4, 6, 8, 0
};
System.out.println(toString(arr));
}
private static String toString(int[] arr) {
String ret = "[";
for (int i = 0; i < arr.length; ++i) {
ret += arr[i];
if (i != arr.length - 1) {
ret += ", ";
}
}
ret += "]";
return ret;
}
}
数组拷贝
先来看一段代码:
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2};
int[] arr2 = arr;
arr[0] = 100;
System.out.println("arr: " + Arrays.toString(arr));
System.out.println("arr2: " + Arrays.toString(arr2));
}
}
注意:上述代码并不是进行数组的拷贝,而是创建了一个新的引用,也就是浅拷贝。
Java中为我们提供了深拷贝的接口,下面我们来看个例子:
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2};
int[] arr2 = Arrays.copyOf(arr, arr.length);
arr[0] = 100;
System.out.println("arr: " + Arrays.toString(arr));
System.out.println("arr2: " + Arrays.toString(arr2));
}
}
我们来实现一下数组的深拷贝:
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2};
int[] arr2 = copyOf(arr, arr.length);
arr[0] = 100;
System.out.println("arr: " + Arrays.toString(arr));
System.out.println("arr2: " + Arrays.toString(arr2));
}
private static int[] copyOf(int[] arr, int len) {
if (arr == null || len <= 0) {
return null;
}
int[] ret = new int[len];
int minLen = len < arr.length ? len : arr.length;
for (int i = 0; i < minLen; ++i) {
ret[i] = arr[i];
}
return ret;
}
}
二维数组
语法如下:
数据类型[][] 数组名称 = new 数据类型[][]{初始化数据};
数据类型[][] 数组名称 = {初始化数据};
我们来个简单的例子理解一下:
public class Test {
public static void main(String[] args) {
int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16}
};
for (int i = 0; i < arr.length; ++i) {
for (int j = 0; j < arr[i].length; ++j) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
}