就是这篇博客,CSDN富文本编辑器里面ctrl+z把我5000字全给弄没了,我真的哭晕在键盘上,最后还是含着眼泪写完了这篇博客,尽量做到比之前更加详细,只要大家的支持和关注,就是误删了八百万字我也重写/(ㄒoㄒ)/~~
好,那我们进入正题

【本节目标】

  1. 理解数组的基本概念
  2. 掌握数组的基本用法
  3. 数组与方法互操作
  4. 熟练掌握数组相关的常见问题和代码

    数组的基本概念

    为什么要使用数组?

    回答:简化代码,集合管理。
    举个简单里例子,我们现在要存入5个学生的JavaSE考试成绩,并对其进行输出
    如果这样写的话,太麻烦了:
    public class TestStudent{ public static void main(String[] args){ int score1 = 70; int score2 = 70; int score3 = 70; int score4 = 70; int score5 = 70; System.out.println(score1); System.out.println(score2); System.out.println(score3); System.out.println(score4); System.out.println(score5); } }
    image.png
    这段代码没有问题,但是过多的话就不好管理,
    它们都有一个共同点,数据类型都是相同的,那么我们就可以利用数组来集约化管理

    什么是数组

    数组:可以看成时相同类型元素的一个集合。在内存中时一段连续的空间。

  5. 数组中存放的元素类型相同

  6. 数组中空间连接在一起
  7. 每个空间有着自己的编号,其首位的位置的编号为0,即数组的下标。

那么在程序中我们应该如何创建数组呢?

数组的创建以及初始化

数组的创建

T[] 数组名 = new T[N];
T:表示数组中存放元素的类型
T[]:表示数组的类型
N:表示数组的长度
int[] array1 = new int[10];//创建一个可以容纳10个int类型元素的数组 double[] array2 = new double[5];//创建一个可以容纳5个double类型元素的数组 String[] array3 = new String[3];//创建一个可以容纳三个字符串元素的数组 public static void main1(String[] args) { int[] array = {1,2,3,4,5,6,7,8,9,10}; int ret = array[2]; System.out.println(ret); // 下标默认从0开始 int[] array2 = new int[]{1,2,3,4,5,6,7,8,9,10}; // 两种是一样的,一般用第一种 int[] array3 = new int[10]; // 不确定里面放什么的话,就用第三种 } }
image.png

数组的初始化

数组的初始化主要分为动态初始化以及静态初始化
1、动态初始化:在创建数组时,直接指定数组中元素的个数
int[] array = new int[10];
2、静态初始化:在创建数组时不直接指定数组元素个数,而直接讲具体的数据内容惊醒指定
语法格式:T[] 数组名称 = {data1,data2,data3……}
public static void main3(String[] args) { int[] array ; // 我们称这样为动态初始化 array = new int[]{1,2,3,4,5}; array = new int[]{9,8,7,6,5}; // 这样重新定义是可以的 int[] array2 = {1,2,3,4,5}; // 我们称这么做为静态初始化 // // array2 = {9,8,7,6,5}这样写会报错,因为定义数组的时候整体赋值,只有一次机会 } public static void main2(String[] args) { double[] array = new double[10]; String[] strings = new String[10]; // 此时我们并没有初始化,但静态初始化虽然没有指定数组的长度,编译器会自动帮你确定 }
注意事项:
👉静态初始化虽然没有指定数组的长度,编译器在编译时会根据{}中的元素个数来确定 数组的长 度
👉静态初始化时,{}中数据类型必须与[]前数据类型一致。
👉静态初始化可以简写,省去后面的new T[]
👉数组也可以按照如下C语言个数创建,但是最好不要这么做咯👇
/*
该种定义方式不太友好,容易造成数据的类型就是int的误解
[]如果在类型之后,就表示数组类型,因此int[]结合在一起写,意思更加明了
*/
int arr[] = {1,2,3};
👉如果不确定数组当中内容时,使用动态初始化,否则建议使用静态初始化
👉静态和动态初始化也可以分为两步,但是省略格式不可以,上面代码中有提到
例如这样就会编译失败→int[] arr3; arr3 = {1,2,3}
👉如果没有对数组进行初始化,数组中元素有其默认值
1、如果数组中存储元素类型为基本类型,默认值时基类类型对应的默认值,如:

类型 默认值
byte 0
short 0
int 0
long 0
float 0.0f
double 0.0
char /u0000
boolean false

2、如果数组中存储元素类型为引用类型,默认值为null.

数组的使用

数组中元素访问

数组在内存中是一段连续的空间,空间的编号都是从0开始的,依次递增,该编号成为数组的下标,数组可以通过下标访问其任意位置的元素。比如:
public static void main3_3(String[] args) { int[] array = new int[]{10,20,30,40,50}; 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]); // 也可以通过[]对数组中的元素进行修改 array[0] = 100; System.out.println(array[0]); }
【注意事项】

  1. 数组是一段连续的内存空间,因此支持随机访问,即通过下标访问快速访问数组中任意位置的元素
  2. 下标从0开始,介于[0,N)之间不包含N,N为元素个数,不能越界,否则会报出下标越界异常。image.pngimage.png

这里的红字异常就是提醒我们使用数组一定要下标谨防越界

遍历数组

所谓的“遍历”是指讲数组中的所有元素都访问一遍,访问是指对数组中的元素进行某种操作,比如:Print.
image.pngimage.png
上述代码可以起到对数组中元素遍历的一个目的,但任然有一些问题:

  1. 如果数组中增加了一个元素,就需要增加一条打印语句
  2. 如果输入里面有100个元素,就需要去写100个打印语句
  3. 如果现在要把打印修改为给数组中每个元素加一个数,会非常麻烦。

那么细心的小伙伴们就会想到了,我们可以运用循环来进行打印。
下面介绍一些循环遍历的方法👇
1、基本for循环
image.pngimage.png
PS:在数组中,我们可以通过 数组对象.length 来获取数组的长度
2、for-each进阶法——for增强版💪
image.pngimage.png
for-each是for循环的另外一种使用方法,能够更方便得完成对数组得遍历。可以避免循环条件和更新语句写错。 (循环每次都会把array数组中的元素逐个赋给x)
3、超级简便toString法
image.pngimage.png
我们会常常这样打印
System.out.println(Arrays.toString(array));
image.png
嗨嗨!每天一个小细节,学到了!

数组是引用类型

初始JVM的内存分布

内存是一段连续的储存空间,主要用来存储程序运行时数据的。比如:

  1. 程序运行时代码需要加载到内存
  2. 程序运行时产生的中间数据要存放在内存
  3. 程序中的常量也要保存
  4. 有些数据可能需要长时间的存储,而有些数据当方法运行结束后就要被销毁

如果对内存中存储的数据不加区分的随意存储,那对内存管理起来会非常麻烦
就像一个房间从这样
image.pngimage.png
经过管理之后变成这样
image.pngimage.png
因此为了管理内存,JVM也对所使用的内存按照功能的不同进行了划分
image.pngimage.png

  • 程序计数器(PC Register):只是一个很小的空间,用来保存下一条执行的指令的地址
  • 虚拟机栈(JVM Stack):与方法调用相关的一些信息,每个方法在执行的时候,都会先创建一个栈帧(啊啊啊啊啊啊啊又是让我破大防的栈帧!),栈帧中包含有:局部变量表、操作数栈、动态链接、返回地址以及其他一些信息,保存的都是与方法执行时相关的一些信息。比如:局部变量。当方法运行结束之后,栈帧就被销毁了,即栈帧中保存的数据也被销毁了。
  • 本地方法栈(Native Method Stack):本地方法栈与虚拟机栈的作用类似,只不过保存的内容时Native方法的局部变量。在有些版本的JVM实现中(例如HotSpot),本地方法栈和虚拟机栈是一起的。
  • 堆(Heap):JVM所管理的最大内存区域。使用new创建的对象都是在堆上保存的(例如new int[] {1,2,3}),堆是随着程序开始运行时而创建,随着程序的退出而销毁,堆中的数据只要还有在石油,就不会被销毁。
  • 方法区(Method Area):用于存储已经被虚拟机加载的类信息、常量、静态变量、即使编译器编译过后的代码等数据。方法编译出来的字节码就是保存在这个区域内的

image.pngimage.png
image.pngimage.png
我们在C语言中一般都需要用malloc();来开辟动态内存,然后再去用free()释放
但是在Java中,堆上开辟的内存不需要我们进行释放,JVM本身具有的垃圾回收机制可以帮我们进行这些操作
这一块的内容就不多做解释了,等以后我了解得更透彻更详细会再进行细说

基本类型变量与引用类型变量的区别

基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的时其所对应的值;
而引用数据类型创建的变量,我们一般称之为对象的引用,其空间中存储的是对象所在空间的地址值。