【Java 基础语法】深度剖析 Java 中的数组(1)

int[] array1 = {1,2,3,4,5};

  1. 动态初始化

int[] array2 = new int[5]; // 默认元素为0

// 打印结果为:[0, 0, 0, 0, 0]

  1. 动态初始化

int[] array3 = new int[]{1, 2, 3, 4, 5};

注意事项

  • Java 中 [] 符号,可以写在变量名前面(写在后面也行)。而这样我们可以更好的理解,上述数组的类型是 int[]
  • 数组类型中的 [] 内不能写数值
  • 静态初始化的时候,数组元素个数和初始化数据的格式是一致的

3. 数组的使用

  1. 和 C 语言一样,Java 中访问数组的某个元素直接使用 [] 获取就行,如

int[] array = {1, 2, 3};

System.out.println(arrary[1]);

// 打印结果为:2

注意事项

使用 [] 需要注意,下标范围为[0,length - 1]。如果越界将会出现以下异常java.lang.ArrayIndexOutOfBoundsException

  1. 在 Java 中如果要遍历数组的话,有多种方法
  1. 法一(使用循环语句)

int[] array = {1, 2, 3};

for(int i = 0; i <array.length; i++){

System.out.println(array[i]);

}

在 Java 中,如上述代码使用 数组对象.length 就可以得到该数组的长度

  1. 法二(使用增强 for 循环 for-each)

int[] array = {1, 2, 3};

for(int x : array){

System.out.println(x);

}

如上述代码,该语句会便利数组 array,并且每次都会将数组的元素保存在变量 x 中

  1. 法三(使用 Arrays 类中的 toString 方法)

// 使用 Arrays 类前先导入它的包

import java.util.Arrays;

public class TestDemo{

public static void main(Strings[] args){
    int[] array = {1, 2, 3};
    String ret = Arrays.toString(array);
    System.out.println(ret);
}

}

// 打印结果为:[1, 2, 3]

Arrays 类 中 toString 的功能就是将当前的数组转换成字符串的形式返回,返回值就是字符串

上述遍历方式各有各的特点,至于什么时候用哪一遍历方式,据情况而定

二、数组作为方法的参数


1. 认识 JVM 内存区域划分

我们知道,一个 Java 文件的执行需要先通过编译变成字节码文件,字节码文件再痛过 Java 虚拟机运行在这里插入图片描述

因为字节码文件是被 JVM 转换成平台所能执行的形式所运行的,那么 JVM 到底是怎样的呢?

JVM 本质其实就是一个用 C/C++ 代码实现的软件,它的内存被划分五块为如图所示的样子在这里插入图片描述

那么这里面的各块都分别有啥意义呢?

  • 程序计数器:是一个很小的空间,保存下一条执行的指令地址(通俗的来说就是你本来在敲代码,你老妈喊你去吃饭,但你吃完饭后还要回来执行完你没敲完的代码)在这里插入图片描述
  • Java 虚拟机栈:这就是我们平常说的栈,它重点是存储局部变量(像上面创建的数组 int[] array = {1, 2, 3} 的存储地址的引用就是保存在这里)
  • 本地方法栈:本地方法栈与虚拟机栈的作用类似,只不过保存的内容是 Native 方法的局部变量(在有些版本的 JVM 的实现中(例如 HotSpot),本地方法和虚拟机栈是一起的)
  • 堆:这就是我们平常说的堆,是 JVM 所管理的最大的内存区,使用 new 创建的对象都是在堆上保存(例如 int[] array = new int[]{1, 2, 3}
  • 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据(方法编译出的字节码就是保存在这里)
  • 运行时常量池:这个是方法区的一部分(上述未画出),存放字面量(字符串常量)与符号引用(注意:从 JDK 1.8 开始,运行时常量池在堆上)

补充(Native 方法)

JVM 是一个基于 C++ 实现的程序,在 Java 程序执行过程中,本质上也需要调用 C++ 提供的一些函数和操作系统底层进行一些交互。因此在 Java 开发中也会调用到一些 C++ 实现的函数

既然知道了 JVM 的一些知识点,那么我们就可以对我们上述三种创建数组的代码做一个存储区域分析

int[] array1 = {1,2,3,4,5};

int[] array2 = new int[5];

int[] array3 = new int[]{1, 2, 3, 4, 5};

分析结果如图

在这里插入图片描述

  1. 我们知道,array1、array2、array3 是局部变量,所以它们会在栈上开辟一块内存。
  1. Java 中的数组都属于对象,而对象保存在堆中(对象就是一个实体,比如实际生活中的花草树木,或者上述代码中的 {1, 2, 3, 4, 5} 或者用更加规范的方式 new 出来的对象)
  1. 而保存在堆上的对象又有着自己的内存。上述三个局部变量又是引用变量(即这个变量里面存储的是一个地址),它们将会存储对应将每个对象的元素的首地址
  1. 按照术语来说,用array1举例就是:array1 就是一个引用,它引用了一个对象(指向一个对象)

2. 数组传参以及被调用的过程

我们直接通过一个图片来感受下面代码中数组传参以及被调用的过程

public static void main(String[] args){

int[] array = {1, 2, 3};

print(array;)

}

public static void print(int[] array){

for(int x : array){

System.out.print(x + " ");

}

}

// 打印结果为:1 2 3

在这里插入图片描述

3. 理解引用类型

从上图我们可以知道,参数传数组类型,实参和形参其实都是引用,共同指向同一个对象。

因此如果形参将对象的值改变,那么实参的值也随即改变。可以用一个代码举例

public static void main(String[] args){

int[] array = {10, 20};

System.out.print(“交换前:array[0] = " + array[0] + " array[1] =” + array[1]);

System.out.println();

swap(array);

System.out.print(“交换后:array[0] = " + array[0] + " array[1] =” + array[1]);

}

public static void print(int[] array){

int tmp = array[0];

array[0] = array[1];

array[1] = tmp;

}

// 结果为:

// 交换前:array[0] = 10 array[1] = 20;

// 交换后:array[0] = 20 array[1] = 10;

为了在理解上更加清晰,我们再举一个例子

public static void main(String[] args){

int[] array1 = {1, 2, 3};

int[] array2 = array1;

}

我们可以说 array2 这个引用指向 array1 这个引用吗?不能!这其实是表述有误!

引用不能说指向引用,引用只能说指向另一个引用所指的对象。故我们应该理解成:array2 这个引用指向了 array1 这个引用所指向的对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值