本篇博客将讲解Java中的数组。
文章目录
- 数组的基本用法
- 什么是数组
- 创建数组
- 基本语法
- 代码示例
- 数组的使用
- 计算数组长度
- 打印数组
- for循环打印数组
- 使用for each打印数组
- 使用Arrays打印数组
- 数组在内存中的存储
- 初始JVM内存区域划分
- 理解内存
- 理解引用
- null
- 数组作为方法的参数
- 基本用法
- 传参示意图
- 数组作为方法的返回值
- 拷贝数组
- for循环拷贝数组
- Arrays.copyOf拷贝数组
- Arrays.copyOfRange拷贝数组
- System.arraycopy拷贝数组
- clone拷贝数组
- 二维数组
- 基本语法
- 代码示例
- 二维数组的存储
- 二维数组的打印
- for循环打印二维数组
- for each打印二维数组
- Arrays.deepToString打印二维数组
数组的基本用法
什么是数组
数组是一块连续的内存,所存放的是一组相同数据类型的集合。
创建数组
基本语法
// 动态初始化
数据类型[] 数组名称 = new 数据类型 [] { 初始化数据 };
// 静态初始化
数据类型[] 数组名称 = { 初始化数据 };
代码示例
int[] array1 = {1,2,3,4,5,6,7,8,9};
int[] array2 = new int[10];
int[] array3 = new int[]{1,2,3,4,5};
数组的使用
计算数组长度
直接使用数组名.length即可。例如:
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
System.out.println("数组长度为" + array.length);
}
结果为:
打印数组
for循环打印数组
例如:
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
结果为:
使用for each打印数组
for each也称为增强for循环。使用方法为 for(表达式1 : 表达式2) 。表达式1表示数组的元素类型,表达式2是数组名。
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
for(int x : array) {
System.out.println(x);
}
}
结果为:
使用Arrays打印数组
Arrays是帮助我们操作数组的工具类。Arrays.toString是将当前数组转化为字符串的形式进行输出 例如:
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
System.out.println(Arrays.toString(array));
}
结果为:
数组在内存中的存储
初始JVM内存区域划分
-
程序计数器 (PC Register):只是一个很小的空间,保存下一条执行的指令的地址。
-
虚拟机栈(JVM Stack):重点是存储局部变量表(当然也有其他信息)。我们刚才创建的 int[] arr 这样的存储地址的引用就是在这里保存。
-
本地方法栈(Native Method Stack):本地方法栈与虚拟机栈的作用类似,只不过保存的内容是Native方法的局部变量。在有些版本的 JVM 实现中(例如HotSpot),本地方法栈和虚拟机栈是一起的。
-
堆(Heap):JVM所管理的最大内存区域。使用new创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2, 3} )
-
方法区(Method Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法编译出的的字节码就是保存在这个区域。
-
运行时常量池(Runtime Constant Pool):是方法区的一部分,存放字面量(字符串常量)与符号引用。(注意从JDK1.7开始,运行时常量池在堆上)
局部变量和引用保存在栈上,new出的对象保存在堆上。
堆的空间非常大,栈的空间比较小。
堆是整个 JVM 共享一个,而栈每个线程具有一份(一个 Java 程序中可能存在多个栈)。
理解内存
内存就是指我们熟悉的 “内存”。内存可以直观的理解成一个宿舍楼。有一个长长的大走廊,上面有很多房间。每个房间的大小是1Byte (如果计算机有 8G 内存, 则相当于有 80亿 个这样的房间)。每个房间上面又有一个门牌号,这个门牌号就称为 地址 。
理解引用
对于数组的存储,我们暂时只考虑两块区域——栈区和堆区
例如:
int[] array1 = {1,2,3,4,5};
int[] array2 = new int[]{1,2,3};
array1和array2就是引用,也称为引用变量。这个变量里面储存的是一个地址(假设这两个数组的地址为0x123和0x456)。
null
int[] array = null;
这行代码代表array这个引用不指向任何一个对象。
数组作为方法的参数
基本用法
例如打印数组:
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
print(array);
}
public static void print(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
结果为:
传参示意图
数组传参传递的是当前引用的值——地址。
数组作为方法的返回值
例如:
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
int[] ret = func(array);
System.out.println(Arrays.toString(ret));
}
//将原数组各个元素都乘以二,然后赋值给一个新数组
public static int[] func(int[] array) {
int[] ret = new int[array.length];
for (int i = 0; i < array.length; i++) {
ret[i] = array[i] * 2;
}
return ret;
}
结果为:
因此,数组作为方法的返回值的时候,返回的仍然是地址。
拷贝数组
for循环拷贝数组
例如:
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
int[] ret = new int[array.length];
for (int i = 0; i < array.length; i++) {
ret[i] = array[i];
}
System.out.println(Arrays.toString(ret));
}
结果为:
Arrays.copyOf拷贝数组
Arrays.copyOf传两个参数,第一个是数组名称,第二个是拷贝的长度。 例如:
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
int[] ret = Arrays.copyOf(array,array.length);
System.out.println(Arrays.toString(ret));
}
结果为:
Arrays.copyOfRange拷贝数组
Arrays.copyOfRange可以选择拷贝区间,第一个参数是数组名称,第二参数是起始位置,第三个参数是终止位置。范围遵循左闭右开的规则。 例如:
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
int[] ret = Arrays.copyOfRange(array,1,3);//[1,3)
System.out.println(Arrays.toString(ret));
}
System.arraycopy拷贝数组
System.arraycopy使用方法如下:
从src的srcPos开始拷贝,拷贝到dest的destPos位置。拷贝长度是length。
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6,7};
int[] ret = new int[array.length];
System.arraycopy(array,0,ret,0,array.length);
System.out.println(Arrays.toString(ret));
}
结果为:
clone拷贝数组
例如:
public static void main(String[] args) {
int[] array1 = {1,2,3,4,5,6,7};
int[] ret = array1.clone();
System.out.println(Arrays.toString(ret));
}
结果为:
二维数组
基本语法
数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };
例如:
int[][] array1 = {{1,2,3},{4,5,6}};
int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
int[][] array3 = new int[2][3];
int[][] array4 = new int[2][];
Java中二维数组不可省略行。
代码示例
例如打印数组:
public static void main(String[] args) {
int[][] array = {{1,2,3},{4,5,6}};
for (int i = 0; i < 2; i++) {
for(int j = 0; j < 3; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
结果为:
二维数组的存储
例如:
int[][] array = {{1,2,3},{4,5,6}};
array这个数组,本身长度为2,每个元素又是一个一维数组。
我们可以验证一下:
public static void main(String[] args) {
int[][] array = {{1,2,3},{4,5,6}};
System.out.println(array.length);
System.out.println(array[0].length);
System.out.println(array[1].length);
}
结果为:
二维数组的打印
for循环打印二维数组
例如:
public static void main(String[] args) {
int[][] array = {{1,2,3},{4,5,6}};
for (int i = 0; i < array.length; i++) {
for(int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
结果为:
for each打印二维数组
例如:
public static void main(String[] args) {
int[][] array = {{1,2,3},{4,5,6}};
for(int[] arr : array) {
for(int x : arr) {
System.out.print(x + " ");
}
System.out.println();
}
}
结果为:
Arrays.deepToString打印二维数组
例如:
public static void main(String[] args) {
int[][] array = {{1,2,3},{4,5,6}};
System.out.println(Arrays.deepToString(array));
}
结果为:
本篇博客到此结束。
上一篇博客:Java学习苦旅(五)——方法?方法!!!
下一篇博客:Java学习苦旅(七)——我有对象啦!!!