##################################################
目录
什么是数组
数组的概念
数组原理
Java 中的数组
Java 内存中数组的储存方式
Java 数组长度概念
Java 数组
声明定义一个数组
为数组分配空间
边声明边分配空间
动态初始化数组
静态初始化数组
引用数组元素
数组元素初始值
数组长度
foreach 循环/增强型 for 循环
关于数组的两个错误
数组下标逻辑错误
数组访问越界错误
##################################################
——————————
数组对于每一门编程语言来说都是重要的数据结构之一
当然不同语言对数组的实现及处理也不尽相同
Java 语言中提供的数组是用来存储固定大小的同类型元素
我们现在学了几种不同的数据类型
例如
int 整形
char 字符型
double 浮点型
String 字符串型
等等
但是有个问题 一个变量只能储存一个数据!!
当我们需要临时记录一百个数据的时候难道要挨个声明一百个变量吗??!
这个时候 数组就派上用场了!
你可以声明一个数组变量,如
numbers[100]
来代替直接声明 100 个独立变量:
number_0, number_1, ......, number_99
我们有时候需要对数据类型相同,用途相近的一组数据集中进行处理,这就是数组!
例如 统计一组 vip 用户充了多少钱等。。
在 Java 编程中数组和循环往往是最佳搭档!!
这两个金牌搭档在结合在一起 可以大大简化代码 提高效率
我们普遍使用 for 循环遍历数组或者给数组元素赋值
——————————
数组就是一个变量 用于将相同数据类型的数据存储在内存中
数组中的每一个数据元素都属于同一种数据类型
前面说过 变量就是在内存空间中分配一块合适的空间
然后将数据储存在这个空间中 数组就是在内存空间中划出一串连续的空间
——————————
在 Java 中,数组也是一个变量,用于将相同数据类型的数据储存在内存中
数组中的每一个元素都属于同一数组类型
例如:
int 整型数组
char 字符型数组
double 小数数组
String 字符串数组
偷偷告诉你 其实 这个变量储存的是值的地址
在 C 语言中假如一个 int 数组地址为 5211314
int 占用 4 字节 32 位
则下一个元素位置为 5211314 + 32 = 5211346
数组中的值储存在内存中 然后把她们储存在哪都记下来
当然 现在我们没必要这么深入 只知道数组很方便就行了
——————————
数组的存储方式:
标识符
跟 变量/常量 一样 数组也要有一个名称,即 标识符 以此来区分不同的数组
数组只有一个 标识符/数组名数组元素
有了名字 就要向数组中存放数据了
这些储存的数据 就称之为数组元素数组下标
数组元素在数组中顺序排列编号 就可以顺序存取数据了!
这个编号称之为下标
根据下标 我们就能正确的得到数组元素
每个元素固定对应一个下标 标明了元素在数组中的位置 我们可以通过下标来达到访问数据的目的
第一个元素的编号为 0 然后才是 1、2、3、4、N
即 数组下标从 0 开始元素类型
储存在数组中的元素 绝对是同一数组类型!
例如 全是整数数据的数组 我们称之为 整形数组 元素类型是整形
示例内存中的数组存储:
10 20 30 40 50 ... N /* 元素 */
0 1 2 3 4 ... N /* 下标 */
假如该数组名字为 a
则
数组名为 a
数组元素为 10、20、30、40、50、N
对应下标为 0、1、2、3、4、N
我们通过下标来访问储存的元素:
下标 0 代表 10
下标 1 代表 20
下标 2 代表 30
下标 3 代表 40
下标 4 代表 50
下标 N 代表 N
——————————
数组的 大小/长度 就是数组可容纳元素的最大数量
当我们定义一个数组的同时也定义了她的大小
这里有个数组越界的概念 什么是数组越界呢?
当数组已经满了 不能再储存数据了 我们还要储存数据 程序便会出错终止!
这就是数组越界!
10 20 30 40 50 /* 元素 */
0 1 2 3 4 /* 下标 */
假如这个数组固定大小为 5
下标是 0 到 4 这 5 个空间
但是你偏偏要去读取下标 6
当然会报错!
##################################################
——————————
声明一个一维数组的方式:
数据类型 [] 数组名;
数据类型 数组名[];
这两种方式形式上没有任何区别 效果也完全一样
例如:
int [] a; /* 声明一个整数型数组 a */
double b []; /* 声明一个小数型数组 b */
char c[]; /* 声明一个字符型数组 c 也就是一个字符串 */
String[] d; /* 声明一个字符串数组 d 也就是一堆字符串!!这个要跟 char[] 分清!!! */
上面这两种方式都可以声明一个数组 数组名的命名必须是合法的
跟变量命名一样!
好 声明数组 并没有为数组分配内存空间
也就是 只是告诉编译器 我们先声明了一个数组 并没有储存什么
这个时候还不能使用数组 跟变量的概念类似
只有分配了空间 才能使用 才能赋值 才能储存数据!
——————————
只有为数组分配内存空间 数组中的元素才能对应一个储存单元
也就是赋值
分配空间就是跟机器说 在内存中分配一些连续的空间来储存数据
与 C/C ++ 不同
Java 在定义数组时并不为数组元素分配内存空间
因此 [] 中无需指定数组元素的个数 也就是数组长度
所以我们需要先分配内存空间才能访问数组中的元素
我们可以用 new 关键字来给数组分配空间
单独为某个数组开辟内存空间:
数组名 = new 数据类型[数组长度];
数组长度就是数组中能存放的元素个数!应该为大于 0 的整数!
示例:
int [] a; /* 声明一个 int 型数组 a */
a = new int[30]; /* 定义数组 a 的长度为 30 为 int 数组变量 a 指定数组元素个数为 3 即分配内存空间为 3 */
double b [] = new double[40]; /* 声明定义一个长度为 40 的小数数组 b 这样等于在定义 double 数组变量的时候为其分配内存空间 */
char c[] = new char[100]; /* 长度为 100 的字符型数组 c */
String[] d = new String[10]; /* 长度为 10 的字符串型数组 d */
——————————
与变量一样 声明数组的时候同时可以同时分配空间
边声明数组边分配空间:
数据类型[] 数组名 = new 数据类型[数组长度];
一定要记住 数组的长度是固定的 数组的大小一经定义便不可修改!
例如我们声明的 d 数组:
String[] d = new String[10];
突然发现 10 个不够用 想储存 11 个数据。。 想把数组长度改成 11
不可能!只能重新声明新的数组
——————————
声明定义一个数组 即告诉编译器你要声明数组
分配空间 告诉机器在内存开辟合适的空间
到了赋值 既然空间开辟出来了 就可以向数组中存放数据了!
我们已经知道 数组中的每一个元素都是通过下标来访问的
所以我们可以通过访问下标来进行赋值和调用
通过下标对数组元素进行赋值:
通过下标访问数组语法:
数组名 [下标值];
示例:
String[] str = new String[10]; /* 先声明定义一个字符串数组 */
str[0] = "第一个"; /* 之后进行初始化 */
str[1] = "第二个";
str[2] = "第三个";
str[3] = "第四个";
str[4] = "第五个";
str[5] = "第六个";
str[6] = "第七个";
str[7] = "第八个";
str[8] = "第九个";
str[9] = "第十个";
——————————
在声明数组的同时进行初始化
静态初始化数组将 声明数组、分配空间、赋值元素 合并完成:
第一种方式:
数据类型[] 数组名 = { 元素值_1, 元素值_2, 元素值_3, ...... 元素值_N };
第二种方式:
数据类型[] 数组名 = new 数据类型[] { 元素值_1, 元素值_2, 元素值_3, ...... 元素值_N };
第二种方式
new 数据类型[]
[] 中必须为空!
示例:
int[] arr = { 10, 20, 30, 40, 50 }; /* 创建一个长度为 5 的数组 有几个值 此数组长度就是多少 */
int[] arr = new int[] {10, 20, 30, 40, 50}; /* 与上面数组等价 */
这种直接创建并赋值的方式 推荐在数组元素比较少的时候使用
而且必须一并完成 如果这样就不行:
int[] arr;
arr = { 10, 20, 30, 40, 50 };
——————————
今天使用 Slackware 15 Linux 系统编写 Java 程序!
安装的 JDK 18
关于怎么在 Slackware 系统上本地安装 Java 可以看这篇博客 Linux 系统通用:
1.7_如何在虚拟机上的 Linux 系统本地安装配置 Oracle Java 18 环境_燃吹的博客-CSDN博客Linux 通用的本地安装 Java 方式解压 tar.gz 压缩包配置软连接或者环境变量详解 Java 环境变量Slackware 上如何安装 Java 环境!全网最全 Linux Java 环境配置!https://blog.csdn.net/m0_67268286/article/details/124834177
test.java Code:
public class test {
public static void main(String[] args) {
int[] arr = new int[15];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
for ( int i = 1; i <= 15; i ++ )
if ( arr[i - 1] != 0 )
System.out.println ( "[" + (i - 1) + "]:" + arr[i - 1] );
else
System.out.printf ( "[%d]:%d\n", (i - 1), arr[i - 1] );
}
}
Slackware Demo:
# java test.java
[0]:1
[1]:2
[2]:3
[3]:4
[4]:5
[5]:0
[6]:0
[7]:0
[8]:0
[9]:0
[10]:0
[11]:0
[12]:0
[13]:0
[14]:0
#
创建一个 int 数组 数组大小为 15
只将前 5 个元素初始化 遍历输出数组
发现没有初始化的数组元素默认为 0
——————————
不同类型的数组元素默认值如下:
int 0
double 0.0
char '\u0000'
String null
boolean false
如果定义的数组是基本数据类型的数组
且没有指定初始值 就会根据数据类型的不同 给元素赋一个默认值:
boolean 类型定义的数组,默认值是 false
int 类型定义的数组,初始化默认是 0
float 类型定义的数组,默认值是 0.0
double 类型定义的数组,默认值是 0.0
char 类型定义的数组,使用 UTF 8 字符集 给出的结果是 0
String 类型定义的数组,默认值是 null
——————————
得到数组的最大长度方法:
数组.length
因为数组一经创建 数组中包含元素的数目 也就是数组长度 就不能再改变了
如果越界访问 即 数组下标超过 0 至数组长度 -1 的范围 便会报错!
如果我们要使用数组长度 一般都是使用 length 得到的!
数据一经创建 其长度是不可改变的 如果越界访问 程序会报错
与 C、C++ 不同 Java 对数组元素要进行越界检查以保证安全性
每个数组都有一个 length 属性来指明她的长度 例如
intArray.length
指明数组
intArray
的长度
因此 当我们需要使用数组长度的时候 使用如下方式:
数组名.length
例如 拿来进行比较:
i < num.length;
而不是像
i < 5;
注意 length 不是一个方法!
——————————
在 JDK 5.0 中添加了一个新的特性 foreach 循环
她是一种更加简洁的 for 循环,也称为 增强 for 循环
使用 增强 for 循环 需要注意她的局限性:
在遍历集合和数组时,只能访问集合中的元素,不能对其中的元素进行修改
增强 for 循环 并不能修改数组中元素的值
只是将临时变量指向了一个新的字符串,这和数组中的元素没有一点关系!
而在普通 for 循环 中,是可以通过索引的方式来引用数组中的元素比将其值进行修改
当然 好处也很明显 简化遍历!
语法格式:
for ( 元素数据类型 变量名 : 数组或者 Collection 集合 ) {
/* 处理元素 */
}
这次使用 CentOS 7 原生的 Open JDK 8
CentOS 7 原生 Java 环境天生不全 需要安装开发包:
1.3_VMare 16 虚拟机安装配置 CentOS-7-x86_64-DVD-2009+GUI+原生 Java 1.8+ibus+VMware Tools_燃吹的博客-CSDN博客VMware 虚拟机怎么进 BIOS 设置第一启动项CentOS 7 GNOME 安装配置 ibus 中文输入Open Java 1.8 原生开发环境重新安装虚拟机增强工具变灰等问题以及卸载https://blog.csdn.net/m0_67268286/article/details/124632327
下面将 for 与 foreach 进行对比
test.java code:
import java.util.Scanner;
public class test {
public static void main(String[] args) {
Scanner sc = new Scanner ( System.in );
System.out.print ( "请输入循环次数 <<< " );
int num = sc.nextInt(); /* 指定数组长度 */
int[] arr = new int[num]; /* 建立一个定长数组! */
System.out.println ( "—————————— 循环录入 ——————————\n" );
for ( int i = 0; i < num; ) {
/* 循环录入 */
System.out.printf ( "请输入 arr[%d] <<< ", i ++ );
arr[i - 1] = sc.nextInt();
}
System.out.println ( "—————————— 普通 for ——————————\n" );
for ( int i = 0; i < arr.length; i ++ )
/* for 循环遍历 arr 数组 */
System.out.printf ( "arr[%d]:%d\n", i, arr[i] );
System.out.println ( "—————————— foreach ——————————\n" );
for ( int i : arr )
/* foreach 遍历 */
System.out.print ( i + "\n" );
System.out.println ();
}
}
CentOS 7 demo:
[lilian@CentOS javaTest]$ javac test.java
[lilian@CentOS javaTest]$ java test
请输入循环次数 <<< 5
—————————— 循环录入 ——————————
请输入 arr[0] <<< 521
请输入 arr[1] <<< 520
请输入 arr[2] <<< 522
请输入 arr[3] <<< 1314
请输入 arr[4] <<< 5211314
—————————— 普通 for ——————————
arr[0]:521
arr[1]:520
arr[2]:522
arr[3]:1314
arr[4]:5211314
—————————— foreach ——————————
521
520
522
1314
5211314
[lilian@CentOS javaTest]$
##################################################
——————————
数组下标是从 0 开始的而不是从 1 开始
这样虽然不会报错可以通过编译 但是运行起来肯定不能达到预想的结果
数组下标永远从 0 开始
code && demo:
/* cmd demo:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
原数组值为 >>>
李一哈 李恰恰 李三岁
现在将第 2 个数组元素修改为 >>>
李二哈
修改后的数组值为 >>>
李一哈 李恰恰 李二哈
C:\Users\byme\javaTest>
*/
public class test {
public static void main ( String[] args ) {
String[] A = new String[] { "李一哈", "李恰恰", "李三岁" };
System.out.println("\t原数组值为 >>> ");
for ( int i = 0; i < A.length; i ++ )
System.out.print ( A[i] + "\t" );
System.out.println ( "\n\t现在将第 2 个数组元素修改为 >>> \n李二哈" );
A[2] = "李二哈"; /* A[1] = "李二哈"; */
System.out.println ( "\t修改后的数组值为 >>> " );
for ( int i = 0; i < A.length; i ++ )
System.out.print ( A[i] + "\t" );
System.out.println();
}
}
——————————
test.java code:
import java.util.Scanner;
public class test {
public static void main ( String[] args ) {
Scanner input = new Scanner(System.in);
int[] A = new int[2];
A[0] = 10;
A[1] = 20;
A[2] = 30;
System.out.println ( A[2] );
}
}
这种越界访问基本上都是在运行中发生错误 编译可以通过但是运行时异常…… demo:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at test.main(test.java:13)
C:\Users\byme\javaTest>
debian demo:
root@Debian:/work/5.Java/3.Test# java test.java
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 2 out of bounds for length 2
at test.main(test.java:13)
root@Debian:/work/5.Java/3.Test#
java.lang.ArrayIndexOutOfBoundsException
意思是数组下标超过范围 就是数组越界
一个异常 异常是什么?这里先理解为 编译器能捕捉到的错误
at test.main(test.java:13)
at 后面 后面给出了出错位置
这里是 test 类中的 main 方法中的 test.java 文件第 13 行
也就是:
A[2] = 30;
这个 bug 是
数组下标从 0 开始 而不是从 1 开始
如果访问数组元素时指定的下标小于 0 或者大于等于数组的长度
都会报错数组下标越界异常数组下标范围是 0 ~ 数组长度-1
这个程序中 数组下标范围是 0 ~ 1
而 A[2] 明显超过了下标范围
解决方法:
可以增加数组长度
也可以删除超出数组下标范围的语句