数组的定义和使用(全是干货)

简介: 数组的定义和使用(全是干货)

数组的定义和使用

文章目录

1.数组的基本概念

1.1 为什么要用数组

假设我们在要统计5个学生的成绩,并对其打印输出,可能会这样写代码

public class Student {
    public static void main(String[] args) {
        int stu1=90;
        int stu2=93;
        int stu3=85;
        int stu4=87;
        int stu5=80;
        System.out.println(stu1);
        System.out.println(stu2);
        System.out.println(stu3);
        System.out.println(stu4);
        System.out.println(stu5);
    }
}

上述代码是没有一点问题的,但是有不好的就是:当我们需要统计大量同学的成绩时,比如20个、50个、100个……时,总不能连续创建这么多的变量,当所有学生的成绩需要加上5分时总不能一个一个的修改成绩吧,这样的效率简直太低了。通过观察我们发现:所有成绩类型都是int型的,因此我们将这些数据存储到一个容器中,方便统一管理。

容器概念

  • 容器:是将多个数据存储到一起,每个数据称为该容器的元素。
  • 生活中的容器:水杯,衣柜,常见的瓶瓶罐罐……
  • b2eceb0f4693d2a9eff58f3e39222e8e.jpg

1.2什么是数组

数组:相同元素的一个集合。在内存中是一块连续的空间,比如我们常见的停车场:


a07e190719671d65582dfdaf4a6f0764.png

数组好比停车场,车位数好比数组的长度,而汽车就是数组的元素。

因此:

  1. 数组存放的元素类型必须相同
  2. 数组的空间是连在一起的
  3. 每个数组空间有自己的编号,初始位置编号是0,即数组的下标。

1.3数组的创建及初始化

1.3.1数组的创建

T[]数组名=new T[N]

T:表示数组中元素的类型

T[]:表示数组的类型

N:表示数组的长度

1.3.2数组的初始化

在Java中数组初始化分两种:

1.动态初始化:在创建数组时,直接指定数组中元素的个数

int[] array=new int[5];

2.静态初始化:创建数组时不指定元素的个数,而直接将具体的数组内容进行指定

int[] array1=new int[]{1,2,3,4,5,6,7};
double[] array2=new double[]{1.1,2.2,3.3,4.4,5.5};
String[] array3={"hello","java"};//这里省略new String[]编译能通过吗?

静态初始化数组时可以省略new T[],但在编译器编译时还是会还原。

静态初始化时,{}中的数据类型必须与[]前的数据类型一致。

int arr[]={1,2,3};//这样初始化可以吗?

Java中数组初始化可以按照C语言中数组初始化的方式,但是这种方法不推荐容易造成数组的类型就是int的误解

  • 如果没有对数组进行初始化,元素中有其默认值
类型 默认值
byte 0
short 0
int 0
long 0
float 0.0f
double 0.0
char /u0000
boolean float
应用类型 null

1.4数组的使用

1.4.1数组元素的访问

数组在内存中是一段连续存在的空间,空间编号都是从0开始,依次递增,编号是数组的下标,数组可以通过下标进行访问数组的元素。数组下标从0开始,介于[0,N)之间不包括N,N为元素个数,不能越界,否则会报错。

int[]array={1,2,3,4,5};
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]);

1.4.2遍历数组

所谓**“遍历”就是将数组中所有元素访问一遍,访问是指对数组的元素进行某种操作。**比如:打印

int[]array={1,2,3,4,5};
for(int i=0;i<array.length;i++){
  System.out.println(array[i]);
}

在数组中可以通过 数组名.length 获取数组的长度

也可以通过for-each遍历数组

int[]arr={1,2,3,4,5};
for(int e:arr){
    System.out.println(e);
}

for-each 是 for 循环的另外一种使用方式. 能够更方便的完成对数组的遍历. 可以避免循环条件和更新语句写错。

2.数组是引用类型

2.1 Java虚拟机(JVM)的内存分布

  1. 内存是一段连续的存储空间,主要用来存储程序运行时数据的。比如:
  2. 程序运行时代码需要加载到内存
  3. 程序运行产生的中间数据要存放在内存
  4. 程序中的常量也要保存
  5. 有些数据可能需要长时间存储,而有些数据当方法运行结束后就要被销毁
    如果对内存中存储的数据不加区分的随意存储,那对内存管理起来将会非常麻烦。

因此JVM也对所使用的内存进行了划分:f23bf5584e7c64aa882492835964b361.png

  • 程序计数器:是一块较小的内存空间,保存下一条执行的指令的地址,它可以看作是当前线程所执行的字节码的行号指示器。
  • 虚拟机栈:Java方法执行的内存模型,每个方法执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至完成的过程,都对应着一个栈帧从入栈到出栈的过程。每当一个方法执行完成时,该栈帧就会弹出栈帧的元素作为这个方法的返回值,并且清除这个栈帧,Java栈的栈顶的栈帧就是当前正在执行的活动栈,也就是当前正在执行的方法。
  • 本地虚拟机栈:本地方法栈和虚拟机栈所发挥的作用是很相似的,只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的。
  • :JVM所管理的最大内存区域. 几乎所有用new 创建的对象都是在堆上保存 (例如前面的 new int[]{1, 2,3} ),堆是随着程序开始运行时而创建,随着程序的退出而销毁,堆中的数据只要还有在使用,就不会被销毁。
  • 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域 。

2.2数组在内存中的存储

1.一个数组的内存图

public static void main(String[] args) {
    int[]arr=new int[]{1,2,3};
    System.out.println(arr);//[I@1540e19d
}    

代码执行结果是**[I@1540e19d**,这是数组内容在内存中的地址。new的内容几乎都存储在堆中,方法中的变量arr保存的是数组的地址。

90150d482c237ce04a38c70fab5975da.png

2.两个数组的内存图

2dd627c05c6b62672e415c3f15dcf150.png

3.数组作为函数参数

3.1参数传基本数据类型

数组内容交换:

    public static void swapArray(int[]left,int[]right){
        int[]tmp=left;
        left=right;
        right=tmp;
    }
    public static void method4(){
        int[]array1={1,2,3,4,5};
        int[]array2={10,20,30,40,50};
        swapArray(array1,array2);
        System.out.println(Arrays.toString(array1));
        System.out.println(Arrays.toString(array2));
    }
    public static void main(String[] args) {
        method4();
    }

执行结果:

e4f430335856ada7602e74adb00dceb6.png

数组内容未发生交换。在方法中,如果修改了形参的指向,实参的指向不发生变化。


3cb23c7f3cabb293c93ad230f57156e0.png

3.2参数传数组类型(引用数据类型)
    public static void swap(int[]num,int i,int j){
        int tmp=num[i];
        num[i]=num[j];
        num[j]=tmp;
    }
    public static void method3(){
        int[]array={10,20,30,40};
        swap(array,0,3);
        System.out.println(Arrays.toString(array));
    }
        public static void main(String[] args) {
        method3();
    }

执行结果:

134c95e02419790ce22723c59f967a95.png

内存分布:64db062dca0fe2694909b3e5c3884d52.png

方法的参数为基本类型时,传递的是数据值. 方法的参数为引用类型时,传递的是地址值.

}

public static void main(String[] args) {

method3();

}

执行结果:
[外链图片转存中...(img-u6uthkjy-1660910375540)]
内存分布:
[外链图片转存中...(img-wdluWpRU-1660910375540)]
> **方法的参数为基本类型时,传递的是数据值. 方法的参数为引用类型时,传递的是地址值.**


目录
相关文章
|
7月前
|
存储 算法 C语言
二维数组程序举例
二维数组程序举例
84 2
|
C语言
C语言之输出一个二维数组中,求每列最大的元素,并存放在另一个数组中
C语言之输出一个二维数组中,求每列最大的元素,并存放在另一个数组中
162 0
|
26天前
|
存储 算法 C语言
C语言中常见的字符串处理技巧,包括字符串的定义、初始化、输入输出、长度计算、比较、查找与替换、拼接、截取、转换、遍历及注意事项
本文深入探讨了C语言中常见的字符串处理技巧,包括字符串的定义、初始化、输入输出、长度计算、比较、查找与替换、拼接、截取、转换、遍历及注意事项,并通过案例分析展示了实际应用,旨在帮助读者提高编程效率和代码质量。
77 4
|
6月前
|
C语言
C语言学习记录——矩阵转换(定义一个数组实现或定义两个数组实现)
C语言学习记录——矩阵转换(定义一个数组实现或定义两个数组实现)
68 0
|
7月前
|
编译器 程序员 C语言
【C语言】变长数组,二分查找和数组之间自动替换的实现
【C语言】变长数组,二分查找和数组之间自动替换的实现
|
7月前
|
存储 C++
定义一堆数组
定义一堆数组
92 1
|
7月前
|
JavaScript Java C++
定义和引用一堆数组
定义和引用一堆数组
43 1
|
C语言
C语言之用指针实现两个数组中元素的相加并存放到第三个数组中
C语言之用指针实现两个数组中元素的相加并存放到第三个数组中
206 0
题目:下列给定程序中函数fun的功能是:从p所指字符串中找出ASCII码值最大的字符,将其放在第一个位置上,并将该字符前的原字符向后顺序移动。
题目:下列给定程序中函数fun的功能是:从p所指字符串中找出ASCII码值最大的字符,将其放在第一个位置上,并将该字符前的原字符向后顺序移动。
109 0
|
自然语言处理 C语言 C++
输入两个整数,求它们按由从大到小的顺序输出。要求使用变量的引用。
输入两个整数,求它们按由从大到小的顺序输出。要求使用变量的引用。