1、nJavaJava编程基础及应用编程基础及应用第第4 4章章 数组数组第第四四章章 数组数组4.1 理解数组 4.2 数组变量的声明4.3 数组的创建和初始化4.4 数组的使用4.5 Foreach循环4.6 深入理解数组4.7 多维数组4.8 本章小结第第四四章章 数组数组4.1 理解数组 4.2 数组变量的声明4.3 数组的创建和初始化4.4 数组的使用4.5 Foreach循环4.6 深入理解数组4.7 多维数组4.8 本章小结4.1 理解数组理解数组nJava的数组是具有相同的数据类型的数组元素的集合。n一旦数组的初始化完成,数组在内存中所占的空间将被固定下,因此数组的长度将不可改变。
2、nJava的数组既可以存储基本数据类型,也可以存储引用类型的数据。n值得指出的是,数组也是一种数据类型,它本身是一种引用类型。例如int是一个基本类型,但int 就是一种引用类型。第第四四章章 数组数组4.1 理解数组 4.2 数组变量的声明4.3 数组的创建和初始化4.4 数组的使用4.5 Foreach循环4.6 深入理解数组4.7 多维数组4.8 本章小结4.2 数组变量的声明数组变量的声明n声明数组,包括声明数组的名字、数组包含的元素的数据类型。nJava中支持两种语法格式来声明数组:数组元素类型 数组名;数组元素类型 数组名;例如:int iArray或者 int iArray表示i
3、nt类型数组,数组中存放的是int类型的数据第第四四章章 数组数组4.1 理解数组 4.2 数组变量的声明4.3 数组的创建和初始化4.4 数组的使用4.5 Foreach循环4.6 深入理解数组4.7 多维数组4.8 本章小结4.3 数组的创建和初始化数组的创建和初始化4.3.1 创建数组对象4.3.2 数组的初始化(1)静态初始化(2)动态初始化4.3.1 创建数组对象创建数组对象 声明一个数组时仅为数组指定了数组名和元素的数据类型,并未指定数组元素的个数,系统无法为数组分配存储空间。要让系统为数组分配存储空间,必须指出数组元素的个数,该工作在创建数组对象时进行。4.3.1 创建数组对象创
4、建数组对象 n数组对象和其他Java对象一样,也用new语句创建;数组名=new 类型标识符元素个数;n元素个数通过整型常量来表示。例如:要表示10个学生的成绩(整型),可以先声明元素的数据类型为int的数组score,再用new运算符初始化数组。int score;score=new int10;4.3.2 数组的初始化数组的初始化(1)静态初始化n静态初始化时由程序员显式指定每个数组元素的初始值,由系统决定数组的长度。静态初始化的语法格式如下:数组名=new 类型标识符数组元素1,数组元素2,数组元素3,.例如:对包含10个学生成绩的score数组进行初始化。Score=new int65
5、,34,78,81,92,89,94,76,67,86;4.3.2 数组的初始化数组的初始化 n除此之外,静态初始化还有如下简化的语法格式:数组名=数组元素1,数组元素2,数组元素3,.n在实际开发过程中,可能更习惯将数组定义和初始化同时完成,代码如下:int Score=65,34,78,81,92,89,94,76,67,86;4.3.2 数组的初始化数组的初始化(2)动态初始化n动态初始化时由程序指定数组的长度,由系统为每个数组元素指定初始值。动态初始化的语法格式如下:数组名=new 类型标识符元素个数;例如:int score=new int5;4.3.2 数组的初始化数组的初始化 n
6、执行动态初始化时,程序员只需要指定数组的长度,即为每个数组元素指定所需的内存空间,系统将负责为这些数组元素分配初始值。数据类型数据类型默认初值默认初值byte0short0int0long0float0.0double0.0charu0000booleanfalse第第四四章章 数组数组4.1 理解数组 4.2 数组变量的声明4.3 数组的创建和初始化4.4 数组的使用4.5 Foreach循环4.6 深入理解数组4.7 多维数组4.8 本章小结4.4 数组的使用数组的使用n数组最常用的用法就是访问数组元素,包括对数组元素进行赋值和取出数组元素的值。n在Java编程语言中,对数组元素进行访问通
7、过数组名和下标:数组名下标 n 下标值从0开始,到数组元素个数减1,如果数组元素是5个,下标从0到4。n 通过调用数组的length方法可以获得一个数组的元素个数(数组长度)。第第四四章章 数组数组4.1 理解数组 4.2 数组变量的声明4.3 数组的创建和初始化4.4 数组的使用4.5 Foreach循环4.6 深入理解数组4.7 多维数组4.8 本章小结4.5 Foreach循环循环nJava中引入了一种增强的foreach循环形式,这种循环遍历数组和集合更加简洁。n使用foreach循环遍历数组和集合时,无须获得数组和集合的长度,foreach循环自动遍历数组和集合的每个元素,其定义如下
8、:for(type variableName:array|collection)/variableName 自动迭代访问每个元素4.5 Foreach循环循环例4.2 foreach循环来遍历数组元素程序运行结果:65 34 78 81 92public class ForEachTest public static void main(String args)int score=new int65,34,78,81,92;/使用foreach循环来遍历数组元素,其中i将会自动迭代每个数组元素for(int i:score)System.out.print(i+);第第四四章章 数组数组4.1
9、 理解数组 4.2 数组变量的声明4.3 数组的创建和初始化4.4 数组的使用4.5 Foreach循环4.6 深入理解数组4.7 多维数组4.8 本章小结4.6 深入理解数组深入理解数组4.6.1 内存中的数组4.6.2 基本数据类型数组的初始化4.6.3 引用类型数组的初始化4.6.1 内存中的数组内存中的数组n数组引用变量只是一个引用,这个引用变量可以指向任何有效的内存,只有当该引用指向有效内存后,才可通过该数组变量来进行访问数组元素。4.6.1 内存中的数组内存中的数组n实际的数组对象被存储在堆(heap)内存中;如果引用该数组对象的数组引用变量是一个局部变量,那么它被存储在栈(sta
10、ck)内存中。数组在内存中的存储示意图如图4-1所示。图4-1 数组在内存中的存储示意图4.6.1 内存中的数组内存中的数组例4.4 数组之间直接赋值。public class ArrayInRam public static void main(String args)/定义并初始化数组,使用静态初始化int p=5,7,21;/定义并初始化数组,使用动态初始化int k=new int4;/输出数组k的长度System.out.println(数组k的长度为:+k.length);/循环输出p数组的元素for(int i=0;i p.length;i+)System.out.println
11、(pi);/循环输出b数组的元素 运行上面的代码后,将可以看到先输出k数组的长度为4,然后依次输出p数组和k数组的每个数组元素,接着会输出k数组的长度为3。4.6.1 内存中的数组内存中的数组n下面结合示意图说明上面程序的运行过程 当程序定义并初始化了p,k两个数组后,系统内存中实际上产生了4块内存区,其中栈内存中有两个引用变量:p和k;堆内存中也有两块内存区,分别用于存储p和k引用所指向的数组本身。此时计算机内存的存储示意图如图4-2所示。图4-2 定义并初始化p,k数组后的存储示意图4.6.1 内存中的数组内存中的数组n当执行上面的粗体字标示代码k=p时,系统会把p的值赋给k,p和k都是引
12、用类型变量,存储的是地址。因此把p的值赋给k后,就是让k指向p所指向的地址。此时计算机内存的示意图如图4-3所示。图4-3 k引用指向p引用所指向数组后的存储示意图4.6.2 基本数据类型数组的初始化基本数据类型数组的初始化n对于基本类型数组而言,数组元素的值直接存储在对应的数组元素中,因此,初始化数组时,先为该数组分配内存空间,然后直接将数组元素的值存入对应数组元素中。4.6.2 基本数据类型数组的初始化基本数据类型数组的初始化例4.5 基本数据类型数组初始化public class PrimitiveArrayTest public static void main(String args
13、)int Array;Array=new int5;for(int i=0;i Array.length;i+)Arrayi=i+5;4.6.2 基本数据类型数组的初始化基本数据类型数组的初始化n下面将结合示意图详细介绍这段代码的执行过程。执行第一行代码int Array;时,仅定义一个数组变量,此时内存中的存储示意图如图4-4所示。图4-4 定义Array数组变量后的存储示意图4.6.2 基本数据类型数组的初始化基本数据类型数组的初始化 当执行Array=new int5;动态初始化后,系统将负责为该数组分配内存空间,并分配默认的初始值;所有数组元素都被赋值为0,此时内存中的存储示意图如图4
14、-5所示。图4-5 动态初始化Array数组后的存储示意图 当循环为该数组的每个数组元素依次赋值后,此时每个数组元素的值都变成程序显式指定的值。显式指定每个数组元素值后的存储示意图如图4-6所示。4.6.2 基本数据类型数组的初始化基本数据类型数组的初始化图4-6显式为每个数组元素赋值后的存储示意图n引用类型数组的数组元素是引用,因此情况变得更加复杂。每个数组元素里存储的还是引用,它指向另一块内存,这块内存里存储了有效数据。n为了更好地说明引用类型数组的运行过程,下面先定义一个Person类。4.6.3 引用类型数组的初始化引用类型数组的初始化public class Person publi
15、c int age;public double height;public void info()System.out.println(我的年龄是:+age+,我的身高是:+height);n下面程序定义一个Person数组,接着动态初始化这个Person数组,并为这个数组的每个数组元素指定值。4.6.3 引用类型数组的初始化引用类型数组的初始化public class ReferenceArrayTest public static void main(String args)/定义一个student数组变量,其类型是PersonPerson students;/执行动态初始化student
16、s=new Person2;/创建一个Person实例,并将这个Person实例赋给wang变量Person wang=new Person();/为wang所引用的Person对象的age、height赋值wang.age=15;wang.height=158;/创建一个Person实例,并将这个Person实例赋给liao变量Person liao=new Person();/为liao所引用的Person对象的age、height赋值liao.age=16;liao.height=161;/将wang变量的值赋给第一个数组元素students0=wang;n下面将结合示意图详细介绍这段代
17、码的执行过程。执行Person students;代码时,这行代码仅仅在栈内存中定义了一个引用变量,也就是一个指针,这个指针并未指向任何有效的内存区。此时内存中存储示意图如图4-7所示。4.6.3 引用类型数组的初始化引用类型数组的初始化图4-7 定义一个students数组变量后的存储示意图 执行初始化,程序对students数组执行动态初始化,系统为数组元素分配默认的初始值:null,即每个数组元素的值都是null。执行动态初始化后的存储示意图如图4-8所示。4.6.3 引用类型数组的初始化引用类型数组的初始化图4-8 动态初始化students数组后的存储示意图 接着的代码定义了wang
18、和liao两个Person实例,定义这两个实例实际上分配了4块内存,在栈内存储了wang和liao两个引用变量,还在堆内存中存储了两个Person实例。此时的内存存储示意图如图4-9所示。4.6.3 引用类型数组的初始化引用类型数组的初始化图4-9 创建两个实例后的存储示意图 然后,程序依次将wang赋给students数组的第一个元素,把liao赋给students数组的第二个元素,students数组的两个数组元素将会指向有效的内存区。此时的内存存储示意图如图4-10所示。4.6.3 引用类型数组的初始化引用类型数组的初始化图4-10 为数组元素赋值后的存储示意图n从图4-10中可以看出,
19、此时wang和students0指向同一内存区,而且它们都是引用类型变量,因此通过wang和students0来访问Person实例的字段和方法的效果完全一样,不论修改students0所指向的Person实例的字段,还是修改wang变量所指向的Person实例的字段,所修改的其实是同一个内存区,所以必然互相影响。4.6.3 引用类型数组的初始化引用类型数组的初始化第第四四章章 数组数组4.1 理解数组 4.2 数组变量的声明4.3 数组的创建和初始化4.4 数组的使用4.5 Foreach循环4.6 深入理解数组4.7 多维数组4.8 本章小结nJava语言里提供了支持多维数组的语法。Jav
20、a语言里的数组类型是引用类型,因此,数组变量其实就是一个引用,这个引用指向真实的数组内存。数组元素的类型也可以是引用,如果数组元素的引用再次指向真实的数组内存,这种情形看上去很像多维数组。n前面定义一维数组的语法:type arrName;,这是典型的一维数组的定义语法,其中type是数组元素的类型。如果希望数组元素也是一种引用,而且是指向int数组的引用,则可以把type具体成int,那么上面定义数组的语法就是int arrName。4.7 多维数组多维数组n把int类型扩大到Java的所有类型,则出现了定义二维数组的语法:type arrName;n接着对二维数组进行初始化,同样可以把这个
21、数组当成一维数组来初始化,其元素的类型是type类型,则可以采用如下语法进行初始化:arrName=new typelength;上面的初始化语法相当于初始化了一个一维数组,这个一维数组的长度是length。同样,因为这个一维数组的数组元素是引用类型的,所以系统为每个数组元素都分配初始值:null。4.7 多维数组多维数组n使用new typelength初始化这个数组后,相当于定义了length个type类型的变量,当然,这些type类型的变量都是数组类型,因此必须再次初始化这些数组。例4.7 示范了如何把二维数组当成一维数组处理。4.7 多维数组多维数组public class TwoDi
22、mensionTest public static void main(String args)/定义一个二维数组int a;/把a当成一维数组进行初始化,初始化a是一个长度为4的数组/a数组的数组元素又是引用类型a=new int4;/把a数组当成一维数组,遍历a数组的每个数组元素for(int i=0;i a.length;i+)System.out.println(ai);/初始化a数组的第一个元素a0=new int2;/访问a数组第一元素所指数组的第二个元素a01=6;n下面结合示意图来说明这个程序的执行过程。程序的第一行inta;,将在栈内存中定义一个引用变量,这个变量并未指向任何
23、有效的内存空间,此时的堆内存中还未为这行代码分配任何存储区。4.7 多维数组多维数组4.7 多维数组多维数组 程序对a数组执行初始化:a=new int4;,这行代码让a变量指向一块长度为4的数组内存,这个长度为4的数组里每个数组元素都是引用类型,系统为这些数组元素分配默认的初始值:null。此时a数组在内存中的存储示意图如图4-11所示。图4-11 二维数组当成一维数组初始化的存储示意图n接下来的程序对a0元素执行初始化,即让图4-11右边堆内存中的第一个元素指向有效的数组内存,指向一个长度为2的int数组。n因为程序采用动态初始化a0数组,因此系统将为a0所引用数组的每个元素分配默认的初始
24、值:0,然后程序显式为a0数组的第二个元素赋值为6。此时在内存中的存储示意图如图4-12所示。4.7 多维数组多维数组图4-12 初始化a0后的存储示意图n从上面内容可以看出,初始化多维数组时,可以只指定最左边维的大小;当然,也可以依次指定每一维的大小。例如下面的代码:4.7 多维数组多维数组 /同时初始化二维数组的两个维数int b=new int34;n上面代码将定义一个b数组变量,这个数组变量指向一个长度为3的数组,这个数组的每个数组元素又是一个数组类型,它们各指向对应长度为4的int数组,每个数组元素的值为0。这行代码执行后在内存中的存储示意图如图4-13所示。4.7 多维数组多维数组
25、图4-13 同时初始化二维数组两个维数后的存储示意图n还可以使用静态初始化方式来初始化二维数组。使用静态初始化方式来初始化二维数组时,二维数组的每个数组元素都是一维数组,因此必须指定多个一维数组作为二维数组的初始化值。如下代码所示:4.7 多维数组多维数组/使用静态初始化语法来初始化一个二维数组String str1=new Stringnew String3,new String“hello”;/使用简化的静态初始化语法来初始化二维数组String str2=new String3,new String“hello”;上面代码执行后内存中的存储示意图如图4-14所示。图4-14 采用静态初始化二维数组的存储示意图第第四四章章 数组数组4.1 理解数组 4.2 数组变量的声明4.3 数组的创建和初始化4.4 数组的使用4.5 Foreach循环4.6 深入理解数组4.7 多维数组4.8 本章小结n本章中主要介绍了数组的相关内容。首先宏观上介绍数组,认为数组也可以理解成一种特殊的数据类型,它和其他的基本数据类型相似。n其次,详细地讲解了数组的声明、创建到初始化的过程。n接着,介绍数组的使用,包括使用下标对数组进行赋值和遍历以及通过foreach循环对数组内容进行遍历。n最后,深入理解一维和多维数组在内存中的分配情况,并通过举例说明数组在实际编程中的应用。本章小结本章小结