目录
一、数组概念知多少
我们可以将数组看成是相同类型元素的一个集合。
注:
- 数组中存放的元素其类型相同
- 数组的空间是连在一起的
- 每个空间有自己的编号,其实位置的编号为0,即数组的下标
我们可以看到,这其实与现实生活中的车库很相像
(一)创建数组及初始化
数组有三种定义的方式,我们比较常用的是第一种方式
int[] array1 = {1,2,3,4,5,6};//初始化(常用)
int[] array2 = new int[]{1,2,3,4,5,6};//初始化
int[] array3 = new int[10];//创建一个可以容纳10个int类型元素的数组,默认初始为0
数组的初始化分为动态初始化与静态初始化
动态初始化: 在创建数组时,直接指定数组中元素的个数
int[] array = new int[10];
静态初始化:在创建数组时不直接指定数据元素个数,而直接将具体的数据内容进行指定
int[] array = new int[]{1,2,3,4,5,6};
int[] array = {1,2,3,4,5,6};
注:
- 静态初始化虽然没有指定数组的长度,但编译器在编译时会根据{}中元素个数来确定数组的长度
- 静态和动态初始化也可以分为两步,但是省略格式不可以
//正确 int[] array1; array1 = new int[10]; //正确 int[] array2; array2 = new int[]{1,2,3,4,5,6}; //错误!!! int[] array3; array3 = {1,2,3,4,5,6};
(二)使用数组
1.数组中元素访问
数组在内存中是一段连续的空间,空间的编号都是从0开始的,依次递增,该编号称为数组的下标,数组可以通过下标访问其任意位置的元素
public class Test {
public static void main(String[] args) {
int[] array = {123,154,126,200,146,265};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
System.out.println(array[3]);
System.out.println(array[4]);
System.out.println(array[5]);
//通过下标改变数组内某个元素
array[0] = 0;
System.out.println(array[0]);
}
}
注:
- 下标从0开始,介于[0, N)之间不包含N,N为元素个数,不能越界,否则会报出下标越界异常
- 数组是一段连续的内存空间,因此支持随机访问,即通过下标访问快速访问数组中任意位置的元素
2.遍历数组
遍历将数组中的所有元素都访问一遍,这里就要用到循环啦
public class Test {
public static void main(String[] args) {
int[] array = {1,2,3,4,5,6};
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
注:
在数组中可以通过 数组对象.length 来获取数组的长度
二、数组是引用类型哦
(一)初始JVM的内存分布
内存是一段连续的存储空间,主要用来存储程序运行时数据的
- 程序计数器 : 保存下一条执行的指令的地址
- 虚拟机栈: 每个方法在执行时,都会先创建一个栈帧,栈帧中包含有:局部变量表、操作数栈、动态链接、返回地址以及其他的一些信息,保存的都是与方法执行时相关的一些信息。比如:局部变量。当方法运行结束后,栈帧就被销毁了,即栈帧中保存的数据也被销毁了。
- 本地方法栈: 本地方法栈与虚拟机栈的作用类似 ,只不过保存的内容是Native方法的局部变量
- 堆: JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2,3} ),堆是随着程序开始运行时而创建,随着程序的退出而销毁,堆中的数据只要还有在使用,就不会被销毁。
- 方法区: 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据 ,方法编译出的的字节码就是保存在这个区域
现在我们只关心虚拟机栈与堆两块空间 (这也是我们常说的栈和堆)
(二) 基本类型变量与引用类型变量的区别
基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值
引用数据类型创建的变量,称为引用变量(引用),其空间中存储的是对象所在空间的地址
我们可以简单理解为:
引用变量不储存对象本身,而是储存对象在堆中的起始地址
当一个引用变量不指向任何对象时,可以使用null(空引用)
public class Test {
public static void main(String[] args) {
int[] array = null;
System.out.println(array[0]);
}
}
当引用的值为null时,我们对该引用进行读写等操作时会出现空指针异常!!!
这里我敲一串代码来让我们更加深入地了解认识引用变量
小提示:在看我的运行结果之前可以先自己想一下运行结果哦
public class Test {
public static void main(String[] args) {
int[] array1 = {1,2,3,4};
array1[0] = 99;
int[] array2 = array1;
array2[0] = 100;
System.out.println(Arrays.toString(array1));
System.out.println(Arrays.toString(array2));
}
}
最本质的问题就是我们一直在强调的引用变量储存的是对象在堆中的首地址,当把array1的值赋值给array2时,array2指向的对象与array1指向的对象是同一个,通过array1与array2中任何一个引用修改对象的值,另一个引用在访问时该值也是被改变的!
三、数组应用场景大赏
(一)保存数据
public class Test {
public static void main(String[] args) {
int[] array = {1,2,3,4};
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
}
(二)作为函数的参数
首先来看一段代码吧
import java.util.Arrays;
public class Test {
public static void func1(int[] array){
array = new int[]{14,15,16};
}
public static void func2(int[] array){
array[0] = 99;
}
public static void main(String[] args) {
int[] array1 = {1,2,3,4};
func1(array1);
System.out.println(Arrays.toString(array1));
}
}
下面我通过画图的方法来进行详解(array1仍然指向{1,2,3,4})
执行func2时:(传递的是引用,通过引用修改了实参的指向的对象的值)
(三) 作为函数的返回值
public class Test {
//获取斐波那契数列的前n项
public static int[] fib(int n){
if(n <= 0){
return null;
}
int[] array = new int[n];
array[0] = array[1] = 1;
for (int i = 2; i < n; i++) {
array[i] = array[i - 1] + array[i - 2];
}
return array;
}
public static void main(String[] args) {
int[] array = fib(10);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
数组的基础知识大致就是这么多啦,后续会有一些比较经典实用的案例的补充!!!