1.数组是什么呢?
说白了,数组就是一个容器,它主要是用来存储一批同种类型的数据。
2.在学习数组前,我们肯定已经学习了变量,那既然有变量,为什么还要使用数组呢?
通过场景来进行理解,如果存储一个班50个人的数学成绩,那么我们是不是要定义50个变量呢,同理,那如果是一个学校的呢,那我们得要定义多少个变量呢?所以问题也就浮现了,大量变量的定义,实现需求繁琐。因此,我们可以得到一个结论:遇到批量数据的存储和操作时,数组比变量更加适合。
3.如何定义数组来批量存储数据呢?
定义数组有两种方案,一种是静态初始化数组,另一种是动态初始化数组。
3.1.静态初始化数组,在代码中我做了详细的代码说明。
public class array_demo1 {
public static void main(String[] args) {
//定义静态初始化数组
//静态初始化数组的格式
//数据类型[] 数组名 = new 数据类型[]{元素1,元素2......};
//注意:什么类型的数组只能存放什么样类型的数组
//案例:1
int[] ages = new int[]{21, 23, 22};
//还有另一种写法
//数据类型[] 数组名 也可以写成 数据类型 数组名[]
String names[] = new String[]{"张三", "李四", "王五"};//不太建议
//案例2,这是一种简写方法
double[] scores = {88.3,85,4,99};
}
}
写完了静态初始化数组,那么接下来我们需要了解数组在计算机中的基本原理。
计算的程序都是在内存中执行的,数组整个代码也是在内存中执行的,它会在内存中开辟一个空间。
变量存储的就是数组的地址,让后由变量名去指向数组值。大家可以根据以上的静态初始代码中打印一下变量,你会发现它打印的就不是数组的值,而是一个地址值。
我们可以看到整个地址值,左边的[ 表示的数组 I表示它是一个int类型,@表示它在哪个地址,后面的776ec8df就是数组的地址信息。注意,整个数组的地址值是一个16进制的地址信息。
所以:数组变量名中存储的是数组在内存中的地址,数组是一种引用数据类型。
4.数组的访问
4.1数组名[索引];
在上面笔者画的分析图可以发现,数组名就是一个所谓的变量,用来存储数组在内存中的地址。那么也就是说,我们可以通过数组名去找到这个数组了,数组中的每一个数据都是有一个编号的,这个编号默认是从0开始的,在JAVA中也称为索引。那么我们可以通过上面的方法可以访问数组的值。
package demo;
public class demo6 {
public static void main(String[] args) {
int[] ages = new int[]{21, 23, 22};
System.out.println(ages[0]);
System.out.println(ages[1]);
System.out.println(ages[2]);
}
}
但是我们还需要注意一点,那就是数组的索引值有一个范围,不能超过整个范围,否则会报错。
如代码所示:
package demo;
public class demo6 {
public static void main(String[] args) {
int[] ages = new int[]{21, 23, 22};
System.out.println(ages[0]);
System.out.println(ages[1]);
System.out.println(ages[2]);
System.out.println(ages[3]);
}
}
这是一个很经典的错误,数组索引越界。
4.2 数组的赋值
也可以理解修改数组的数据。
如代码所示:
package demo;
public class demo6 {
public static void main(String[] args) {
int[] ages = new int[]{21, 23, 22};
System.out.print("赋值前的数据:");
System.out.print(ages[0] + " ");
System.out.print(ages[1] + " ");
System.out.print(ages[2] + " ");
ages[0] = 55;
ages[1] = 56;
ages[2] = 57;
//起到换行的作用
System.out.println();
System.out.print("赋值后的数据:");
System.out.print(ages[0] + " ");
System.out.print(ages[1] + " ");
System.out.print(ages[2] + " ");
}
}
4.3 数组的长度属性
如果我们想知道数组的长度,我们可以通过 数组名.length 来获取。
如代码所示
package demo;
public class demo7 {
public static void main(String[] args) {
int[] ages = new int[]{21, 23, 22,25};
String[] names = new String[]{"张三", "李四", "王五"};
System.out.println("数组的长度:" + ages.length);
System.out.println("数组的长度:" + names.length);
}
}
4.4 数组的遍历
遍历指的是数组中数据一个一个的访问。
为什么要遍历数组呢?
我们会在数组中存储一批一批的数据,我们也需要对这里的数据进行操作,比如求和,找最大值,最小值,元素搜素之类的操作。
前面数组的访问也可以实现遍历,但是数组的数据一旦变多,那么就会很繁琐。
如代码所示,如何遍历数组。
package demo;
public class demo7 {
public static void main(String[] args) {
int[] ages = new int[]{21, 23, 22, 25};
//记住:索引是从0开始的,所以我们也从0开始遍历
for (int i = 0; i < ages.length; i++) {
System.out.print(ages[i] + " ");
}
System.out.println();
//这种方法也可以遍历数组,但是有一个缺陷,就是不能得到数组的索引,推荐使用上面那种方法
for (int age : ages) {
System.out.print(age + " ");
}
}
}
5 动态初始化数组
定义数组时先不存入具体的元素值,只确定数组存储的数据类型和数组的长度。
注意:静态初始化数组和动态初始化数组的写法是独立的,不可以混用。
如代码所示:
package demo;
public class demo8 {
public static void main(String[] args) {
//定义动态初始化数组
//数据类型[] 数组名 = new 数据类型[长度]
int[] ages = new int[3];
}
}
那么动态初始化数组在计算机中怎么执行的呢?
也会在内存中分配一个变量空间,整个变量存储的还是数组对象的地址。而且整个数组地址一开始还会存储写默认值,后期在往里面进行赋值,下面借用某培训机构的图以供大家学习。
笔者在这里简单的画一个原理图。
5.2 区别两种数组定义的方法分别适用于哪种场景?
1.动态初始化数组:适合那种一开始就不知道具体的元素值,只知道元素个数的业务场景,用户交互性好。
2.静态初始化数组:适合那种一开始就知道要存入哪些元素值的业务场景。
6.数组的执行原理,Java程序的执行原理。
Java在编译之后会产生一个class文件,这个class文件是提取到正在运行的虚拟机里面去。
虚拟机也划分成5个区域,分别是:方法区、栈、堆、本地方法栈、寄存区。
方法区是放我们编译后的class文件。栈内存是方法运行时所进入的内存,变量在方法中,所以变量也在这块区域。堆里面放的都是new出来的东西。
说明:int a =20; int[] ages =new int[3];
a是变量,他是直接放在栈中,a变量中存储的数据就是20这个值。
new int[3] 是创建一个数组对象,会在堆内存中开辟区域存储3个整数。
ages是变量,在栈中,ages中存储的是数组对象在堆内存中的地址值。
7.多个变量指向同一个数组
那么什么是多个变量指向同一个数组呢?
如代码所示:
package demo;
public class demo9 {
public static void main(String[] args) {
int[] arr1 = {11, 22, 33};
//同类型的数值是可以赋值的
int[] arr2 = arr1;
System.out.println(arr1);
System.out.println(arr2);
}
}
我们会发现他们的地址值一样,同理,如果我们改变第一个数组的值,arr2的值也会发生改变,如代码所示。
package demo;
public class demo9 {
public static void main(String[] args) {
int[] arr1 = {11, 22, 33};
//同类型的数值是可以赋值的
int[] arr2 = arr1;
arr1[0]=44;
System.out.println(arr1[0]);
System.out.println(arr2[0]);
}
}
原理图如下:
在这里要提醒一点:如果某个数组变量存储的地址是null,那么该变量将不在指向任何数组对象。
那么它那根线就会断掉,输出它的时候就会为null,如果去访问数据的时候就会报错(空指针异常),访问长度也会出错。
如代码所示:
package demo;
public class demo9 {
public static void main(String[] args) {
int[] arr1 = {11, 22, 33};
//同类型的数值是可以赋值的
int[] arr2 = null;
System.out.println(arr2);
}
}
package demo;
public class demo9 {
public static void main(String[] args) {
int[] arr1 = {11, 22, 33};
//同类型的数值是可以赋值的
int[] arr2 = null;
System.out.println(arr2);
System.out.println(arr2[0]);
System.out.println(arr2.length);
}
}
总结:多个数组中存储的是同一个数组对象的地址。多个变量修改的都是同一个数组对象的数据。
8.个人说明
此文章属于笔者个人的学习心得,由于笔者的能力有限,会出现很多笔者没有想到的问题,如果您在浏览或者运行代码的时候出现了错误还请您在评论区留言,笔者看到后会在第一时间处理。在文章中出现的原理图都是笔者使用world文档画的,会有很多的缺陷,如果影响了您的观看,还请您谅解,谢谢。