已阅读5页,还剩21页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章 实验 数组5.1实验目标(1) 理解在Java中如何声明、分配和使用(多维)数组(2) 学习数组排序和查找的基本算法(3) 了解JAVA Reflection API 和其他常用类5.2实验说明本章实验教程将介绍数组(array)的使用,学习Java数组相关的类Array和Arrays。简单介绍Java反射(Reflection)的用法。以下的实验包括4种类型, 每种类型都用括号里面的字母表示:D - 例程, 表示这是一个例子, 要求练习者阅读指南和代码; I - 交互式练习, 练习者完成实验指定的简单任务,如修改部分代码, 观察程序运行时的变化等; W - 热身练习, 练习者的编程工作量逐渐加大。P - 完整编程 ,要求练习者根据要求,完成完整的JAVA程序。5.3实验准备从本实验教程光盘中拷贝Lab05文件目录到本地磁盘, 如D: 盘。Lab05文件目录中将包含本次实验所需的所有资料。 Lab05的相关资料也可以从本实验教程的网站下载:http:/javaLab/lab05.zip将Lab04中的MathUtility.java(程序清单4-6)程序拷贝到Lab05目录下。5.4实验任务实验5.4.1: (D)数组的基本概念Java变量(variable)可以存储程序的数据,每个变量有标识、类型和作用域。使用同种类型和作用域的多个数据时,我们通常把这些数据存放在一个数据结构而不是单个的变量中。最常见的数据结构是数组(array)。一个数组中能够存储的数据个数是固定的,并且存放的数据类型相同。尽管数组是一个对象,但是数组的用法与基本数据类型相似。图5.1可以帮助我们理解数组的结构。图5.1 长度为8的数组 这是一个有8个元素的数组,数组中的每个元素有各自的值。图中每个元素上方的数字表明了元素的索引(index)。数组中的元素总是使用索引引用的。第一个元素的索引总是为0。重复,第一个元素的索引总是为0,而最后一个元素的索引总是“数组长度-1”。上图的数组中,最后一个元素的索引是 8-1 = 7。 我们可以创建任何数据类型的数组。下面来看一个整型数组的例子。编译并运行ExamScoresl.java,输入0到100之间的一组整数为命令行参数。假设输入的这组整数就是考试成绩,这个程序将显示原始成绩和调整后的成绩。成绩调整的规则是:将最高成绩上调到100分,计算调整的幅度,再根据幅度相应调整其他成绩。程序清单5-1:ExamScores1.java/ Given a sequence of exam scores as/ command-line arguments, displays table/ of exam scores and curved scores.public class ExamScores1 public static void main(String commandLineArgs) if ( commandLineArgs.length = 0 ) System.out.print(Given a sequence of exam scores ); System.out.println(entered as command line arguments,); System.out.print(this program will curve them up ); System.out.println(by raising the highest to 100 and ); System.out.println(raising all others by the same amount.); System.exit(0); / if no command-line arguments / Named constant for width of displayed columns: final int columnWidth = 5; / Named constant for the number of scores: final int numberOfScores = commandLineArgs.length; / Declare reference to array / which will store exam scores: int scores; / Instantiate (create) the array itself, / i.e. allocate space to store the exam scores: scores = new intnumberOfScores; / Read scores into array and determine maximum: int maximumScore = 0; for ( int i = 0; i scores.length; i+ ) scoresi = Integer.parseInt(commandLineArgsi); maximumScore = Math.max(maximumScore, scoresi); / for i / Determine how many points to curve up all scores: int curveUp = 100 - maximumScore; / Output table of original scores and curved scores for ( int i = 0; i scores.length; i+ ) / Print original score in a right-justified column: String scoreText = Integer.toString(scoresi); for ( int j = scoreText.length(); j columnWidth; j+ ) System.out.print( ); System.out.print(scoreText); / Calculate curved score; int curvedScore = scoresi + curveUp; / Print curved score in a right-justified column; String curvedScoreText = Integer.toString(curvedScore); for ( int k = curvedScoreText.length(); k columnWidth; k+ ) System.out.print( ); System.out.println(curvedScoreText); / for i / method main(String) / class ExamScores1大家可能已经发现,ExamScoresl.java源代码中main方法的命令行参数数组的名字与惯常不同,这里使用了commandLineArgs。其实使用什么名字作为命令行参数的数组名并没有关系,只要这个名字在整个main方法中保持一致就行。在一个具体的程序中,我们通常把命令行参数数组取名为args,把命令行参数个数的变量取名为argv,命令行参数数组是一个字符串数组。ExamScoresl.java程序中需要跟踪所有的成绩,因此将考试成绩存放在一个int型数组中。创建数组的三个步骤是:(1)声明一个数组引用变量;(2)实例化(创建)数组本身,也就是为数组分配内存空间;(3)初始化数组中的每个变量。1. 数组的声明数组变量的声明和其他Java变量的声明类似,声明数组的语法模板:DataType ArrayName ConstIntExpression;或DataType ConstIntExpression ArrayName; DataType是数据类型,即数组中元素的数据类型;ArrayName是合法的变量; 符号中的ConsIntExpression指明数组的大小,即数组中元素的个数。程序ExamScoresl.java中,声明int数组变量:int scores;另外一种声明数组的方式:int scores;这两种数组声明方式在语法上都是正确的,都能被编译器接受。编者个人喜欢第一种(int scores)声明方式,因为它更清晰地说明了数组变量的名字是scores,而不是scores;scores被声明为一个指向整型数组的指针。然而,更普遍使用的是第二种方式,尤其在Java官方文档中更为明显,因为这种方式与C+中的声明方式比较接近。2. 实例化数组实例化scores数组的语句如下:scores = new intnumberOfScores;实例化数组,即为数组元素分配内存空间,是通过new操作符实现的。new操作符后是数据类型以及元素个数。元素个数放在运算符中。下面是一些例子: counts = new int5; names = new String100;3. 数组元素的初始化将scores数组中的元素在循环中初始化的语句如下:for ( int i = 0; i scores.length; i+ ) scoresi = Integer.parseInt(commandLineArgsi);scores.length是数组元素的个数,就象commandLineArgs.length是数组commandLineArgs的元素个数一样。数组元素的范围从0到length - 1。4. 数组声明、实例化和初始化的更多解释声明和实例化数组的常见形式如下例所示:int scores;scores = new intnumberOfScores;声明和实例化数组可以合并成一个语句:int scores = new intnumberOfScores;还可以定义初始化列表(Initializer List)来初始化数组元素:int numbers = 4, 3, 2, 1;String name = Zhang, Wang, Li;数组的长度是由中的元素个数隐含定义的,numbers数组的长度为4,name数组的长度为3。当数组的声明和创建分开时,仍然可以使用初始化列表,只是这种方式不太简练:int numbers; numbers = new int4, 3, 2, 1; 再次强调一下,数组变量是一个内存位置的名字,这个内存位置存储的不是数组本身,而是数组在内存中存放的地址。因此,数组变量存放了一个指向数组的指针。当数组变量第一次声明时,它并没有真正指向一个数组。数组声明只是开辟一个存放指针的空间。之后,当使用关键字new实例化数组并将其指定给一个数组变量时,该数组变量就存放了一个指向数组的指针。范例5-1程序的顶端有这样一个声明:final int columnWidth = 5;这个声明看上去象一个变量的声明,不同的是在最前面有一个关键字final。关键字final意味着columnWidth被声明为一个常量。常量的值在第一次初始化之后就不能改变。为什么要费心去定义常量,而不在代码中直接使用常量的值呢?原因在于方便程序员修改程序,程序员只需查看代码顶端并修改常量的值,而不需要修改该常量的值出现的每行代码。实验5.4.2: (I)访问数组元素引用数组中的元素,使用 操作符。范例5-1中,访问scores数组元素:int score = scores0; / 得到第一个元素int score = scores3; / 得到第四个元素 中的索引可以是整数,或者整型变量。索引的取值范围在0到数组元素个数-1之间。数组变量与数组中索引变量的区别在于,数组变量代表整个数组,数组中的索引变量代表了数组中的元素在数组中的位置。通常我们会使用for循环语句来操作数组元素,见范例5-2。程序清单5-2:AccessArrayWithForLoop.javapublic class AccessArrayWithForLoop public static void main(String args) String months = Jan, Feb, Mar, Apr, May, Jun, July, Aug, Sep, Oct, Nov, Dec;int sizes = 31,28,31,30,31,30,31,31,30,31,30,31;for(int i = 0; i months.length; i+ ) System.out.println(monthsi + has + sizesi + days.);注意for循环中的变量i,i的取值在0到months.length-1之间。试着把源代码 for(int i = 0; i months.length; i+ )改成: for(int i = 0; i = months.length; i+ )重新编译、运行程序。回答下面的问题:代码可以正常编译吗?为什么?_程序可以正常执行吗?为什么?_实验5.4.3: (I)查找最大数 GreatestNumber.java(范例5-3)将对话框输入的3个数字保存在数组中,计算出其中的最大值。程序清单5-3:GreatestNumber.javaimport javax.swing.JOptionPane;public class GreatestNumber public static void main(String args) int num = new int10;int counter;int max = 0;int totalnumber = 3;/ Prompt a user to enter numbersfor(counter = 0; counter max)max = numcounter;/ Display the greatest number.JOptionPane.showMessageDialog(null,The number with the greatest value is + max);现在,参照GreatestNumber.java写一个新的程序SmallestNumber.java, 找出3个数中的最小值。实验5.4.4: (W)练习使用数组写一个类似于ExamScores1.java的程序ExamScores2.java,从命令行参数输入学生成绩,没有输入命令行参数时,程序会显示提示信息。要求程序输出成绩列表,以及成绩的最高分和最低分。程序中不使用Math类的max和min方法。实验5.4.5: (P)用数组实现斐波纳契函数编写程序FibonacciArray.java,用数组实现斐波纳契函数。由键盘读入n值(参见实验1.4.15)。程序将在控制台输出此斐波纳契序列f(0),f(1), f(n)。斐波纳契序列的定义如下:如果n = 0 或者 n = 1 , 则 f(n) = 1如果n是一个整数并且n 1 , 则f(n)= f(n-1) + f(n-2)实验5.4.6: (I)字符串和字符数组在Java库文件中查看String类的toCharArray方法。我们提到过String包含一串字符,更准确地讲,包含了一个字符数组以及操作这些字符的大量方法。String类的toCharArray方法将字符串转换为Character数组。toCharArray是一个实例方法还是类方法,查看Java文档,写下结果:_范例5-3使用toCharArray方法实现字符串反转。程序清单5-3:StringReverse.javapublic class StringReverse public static void main(String args) System.out.println(reverse(args0);public static String reverse( String inputString) if (inputString = null)return null;else char charArray = inputString.toCharArray(); /string to char arrayfor (int i = 0; i charArray.length / 2; i+) char temp = charArray i;charArray i = charArray charArray.length - i - 1;charArray charArray.length - i - 1 = temp; String re = new String(charArray); /char array to stringreturn re; / method reverse以上程序的算法如下图所示,程序进行1/2数组长度次的循环,每次调换头尾两个位置中的元素。在第一次循环中,先将位置0上的元素存放在temp变量,然后将位置9上的元素赋值到位置0,最后将temp中元素存入位置9。在第二次循环时,先将位置1上的元素存放在temp变量,然后将位置8上的元素赋值到位置1,最后将temp中元素存入位置8。依次类推,最后一次循环,将位置4和位置5中的元素交换。图5.2 字符串反转算法描述实验5.4.7: (I)传递数组参数用简单类型数据做参数时,Java遵循值传递的原则。实质上,就是将参数值先拷贝一份,然后将拷贝传递给方法。因此,在方法内部修改参数对原来的变量没有影响(因为只是对拷贝的修改),而且,方法返回时,方法调用的空间回收,拷贝的参数空间也被收回。Java中,不能把对象传递给方法,只能传递对象的引用(Reference,即对象的内存地址)。引用本身也是采用值调用。当一个方法接受对象的引用后,它就可以直接操纵对象。尽管数组在语法上有别于其他一般意义上的对象,但数组被Java看作是对象。数组以引用调用的方式传递给方法,数组的引用变量包含一个指针,指向数组在存储器中的实际存储位置。编译并运行程序ValueVsReference.java。程序清单5-4:ValueVsReference.javapublic class ValueVsReference public static void main(String args) short a = 0, 2, 4, 6, 8 ; System.out.println(The values originally stored in the array are:); for ( int i = 0; i a.length; i+ ) System.out.print( + ai); System.out.println(); System.out.println(Lets see how the values change.); modifyPrimitive(a0); for ( int i = 0; i a.length; i+ ) System.out.print( + ai); System.out.println( Method tried to modify primitive element.); modifyArray(a); for ( int i = 0; i a.length; i+ ) System.out.print( + ai); System.out.println( Method modified array.); modifyArrayReference(a); for ( int i = 0; i a.length; i+ ) System.out.print( + ai); System.out.println( Method modified its own reference to array.); / method main public static void modifyPrimitive(short p) p = 20; / method methodA public static void modifyArray(short b) for ( int j = 0; j b.length; j+ ) bj = (short) (j*(-3); / method modifyArray public static void modifyArrayReference(short b) b = new short5; for ( int j = 0; j b.length; j+ ) bj = (short) (j*3); / method modifyArrayReference / class ValueVsReference范例5-4定义了main和其他三个方法modifyPrimitive,、modifyArray和modifyArrayReference。(1) modifyPrimitive 方法修改参数p的值,p是short原始数据类型。因此,此方法的参数转递为值传递。main方法中调用modifyPrimitive方法,传递的实际参数是数组的一个元素a0,此元素的类型也是short原始数据类型。(2) modifyArray方法的参数为数组引用变量b,而不是单独的某个数组元素。方法的头部定义如下:public static void modifyArray(short b)通过引用变量b,可以操纵b指向的数组对象。main方法中调用modifyArray方法,传递的实际参数是数组引用变量a,此时a和b的实际值都是一个指向同一数组对象的指针。modifyArray方法中,对b引用的数组对象的修改,就是对a引用的数组对象的修改。方法调用完成后,变量b的空间被回收,a引用的数组对象被修改。(3) modifyArrayReference 方法内,数组引用变量b 被重新赋值,指向一个新创建的数组:b = new short5;main方法中调用modifyArrayReference方法,传递的实际参数是数组引用变量a。但由于上面的这个赋值语句,形式参数b指向了一个新的数组,而不再指向a引用的数组。对变量b引用的数组对象的任何修改都不会改变变量a引用的数组对象。现在,请写下程序执行后的结果,并认真思考为什么是这样的结果。_实验5.4.8: (W)写一个带有数组参数的方法在MathUtility.java(见程序清单4-6)中,写一个静态方法average,此方法用一个双精度浮点数(double)数组作为参数,并返回此数组中元素的平均值。如果数组长度为0,方法返回值为0,并打印一个标准错误输出流消息。回顾如何定义一个指向double类型数组的指针,并在方法的参数列表中声明。以如下方式定义average方法的方法头:public static double average (double doubleArray)运行AverageTest.java程序测试average方法。程序清单5-5:AverageTestpublic class AverageTest public static void main(String args) if (args.length = 0) System.out.println(This program will average any + number of precision floating-point ); System.out.println(numbers entered as command-line + arguments. Result should be zero); System.out.println(for no command-line arguments.); / if double numbers = new doubleargs.length; for ( int i = 0; i 0 ) System.out.print( + numbers0); for ( int i = 1; i numbers.length; i+ ) System.out.print(, + numbersi); System.out.print( ); / method printArray(double) / class PowerTest4实验5.4.10: (P)简单的数组中的查找在数组中查找某个元素,一种简单的方法是顺序查找法(Linear Search),即,从数组的第一个记录开始,逐个进行数组中元素和给定值的比较。写一个LinearSearch.java程序查找一个字符串中包含多少个指定字符,这个字符串和指定字符由键盘输入。要求输出此字符串中指定字符的位置,及字符总数。实验5.4.11: (D)多维数组1. Java语言中,多维数组(Multi-dimensional arrays)被看作是数组的数组。 二维数组可以被想象成一个二维的表,表里的所有元素有统一的数据类型。一个int类型的二维数组声明如下: int a ; int a; 二维数组的初始化有两种方式:静态初始化和动态初始化。(1) 静态初始化 a =1,2,3,4,5,6,7;图5.3 静态初始化一个二维数组aJava语言中,不要求多维数组每一维的大小相同。(2) 动态初始化int b = new int23;这种方式直接为每一维分配空间,因为是int类型数组,数组中的元素被初始化成0。图5.4 动态初始化一个2行(rows)3列(columns)的二维数组b下面的语句同样实现了数组的初始化:int b = new int2 ; b0 = new int3;b1 = new int3; 二维数组元素的引用方式为:b12 = 5;图5.5二维数组元素的引用2. 编译、运行MultiDimArray.java程序,理解其中各种多维数组的创建:程序清单5-7:MultiDimArray.javaimport java.util.*;public class MultiDimArray static Random rand = new Random(); static int pRand(int mod) /产生1mod之间的随机数 return Math.abs(rand.nextInt() % mod + 1; public static void main(String args) int a1 = /声明2维数组al,并初始化 1, 2, 3, , 4, 5, 6, , ; for(int i = 0; i a1.length; i+)/输出数组al for(int j = 0; j a1i.length; j+) prt(a1 + i + + j + = + a1ij); / 声明三维数组a2,分配固定的空间: int a2 = new int224; for(int i = 0; i a2.length; i+)/输出a2中元素 for(int j = 0; j a2i.length; j+) for(int k = 0; k a2ij.length; k+) prt(a2 + i + +j + + k + = + a2ijk); / 任意长度的三维数组: int a3 = new intpRand(7);/指定第一维的大小为17的随机数 for(int i = 0; i a3.length; i+) a3i = new intpRand(5);/指定第二维大小 for(int j = 0; j a3i.length; j+) a3ij = new intpRand(5);/指定第三维大小 for(int i = 0; i a3.length; i+)/输出a3中元素 for(int j = 0; j a3i.length; j+) for(int k = 0; k a3ij.length; k+) prt(a3 + i + +j + + k + = + a3ijk); / 非基本类型的三维数组: Integer a4 = new Integer(1), new Integer(2), new Integer(3), new Integer(4), new Integer(5), new Integer(6), ; for(int i = 0; i a4.length; i+) for(int j = 0; j a4i.length; j+) prt(a4 + i + + j + = + a4ij); Integer a5; a5 = new Integer3; for(int i = 0; i a5.length; i+) a5i = new Integer3; for(int j = 0; j a5i.length; j+) a5ij = new Integer(i*j); for(int i = 0; i a5.length; i+) for(int j = 0; j a5i.length; j+) prt(a5 + i + + j + = + a5ij); static void prt(String s) System.out.println(s); 实验5.4.12: (P)练习使用多维数组 写一个Matrix.java程序实现两个33的整数矩阵相乘,并将其结果打印到屏幕上,运算过程中要用到嵌套循环及+=这样的复合运算符号,并用“t”调整输出的格式。 int matrixA = 1, 0, 1 , 1, 2, 3 , 1, 4, 5 ; int matrixB = 5, 4, 0 , 4, 8, 1 , 1, 1, 0 ;提示:在写程序之前,仔细分析矩阵相乘的原理,并将matrixA x matrixB的计算结果写在下面,便于纠正程序设计思路。int matrixAB = 实验5.4.13: (D)int数组的冒泡排序在程序中,经常需要将数组中的数据排序。排序对象要能够相互比较,这是排序的前提。范例5-8是对int数组进行冒泡排序的示例。冒泡排序的基本思想:设想被排序的数组R1.N垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上漂浮,如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。算法示例:以升序排列int数组3,6,2,1,5,4,8,7。依次比较相邻的两个数,将小数放在
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 护理安全十大目标课件
- 在建工地安全课件
- 安全生产课件
- 安全培训课件全部
- 2026年感控工作总结分享
- 项目司机安全教育课件
- 高中心理健康安全教育课件
- 开学前的趣味投壶测试卷及答案解析
- 航空专业岗位面试题及答案大全含山航
- 篮球少年身体素质自测题及答案
- 国企办公室笔试考试题库及答案
- 灭火和应急疏散预案范本
- 西语面试题目及答案
- 传承红色弘扬老区精神
- 2026年甘肃农信校园招聘缴费笔试考试参考试题附答案解析
- 酒精所致精神障碍护理
- GB/T 19801-2005无损检测声发射检测声发射传感器的二级校准
- GB/T 13477.3-2017建筑密封材料试验方法第3部分:使用标准器具测定密封材料挤出性的方法
- 《新民主主义论》-课件
- 县卫生健康系统行风建设评分细则
- 预防网络诈骗知识电信诈骗科普应知应会PPT
评论
0/150
提交评论