如果想要存储一连串的数据,就可以选择使用数组来完成。此外,如果某段程序代码块需要反复使用,那么将它定义成一个方法就可以有效简化程序代码。本章将对数组和方法的使用进行详细介绍。
数组的特点是长度固定,并且是由一组相同类型的变量所组成的数据类型,它们以一个共同的名称来表示。数组中每个元素都有一个对应的下标,可以根据下标来获取对应的元素。根据数组存放元素的复杂程序可分为一维数组、二维数组和多维数组。
5.1 一维数组
5.1.1 数组声明
一维数组可以存放上千万数据,并且这些数据的类型都是完全相同的。要想使用数组,必须经过两个步骤:声明数组、分配内存空间。而定义数组的格式有如下两种方式:
语法格式一:
数组类型[] 数组名称; //声明一维数组 数组名称 = new 数据类型[元素个数]; //分配内存空间
说明:“数组类型”是声明数组存放元素的数据类型。“数组名称”是用来统一这组相同数据类型的元素的名称,其命名规则和变量的命名规则相同,推荐使用有意义的名称。数组声明后,接下来就是分配数组存放所需要的内存空间,根据“元素个数”确定其存放空间大小。“new”则是让编译器根据括号是的“元素个数”在内存中开辟一块内存供数组使用。
int[] data; data = new int[4];
上面代码中,第一行声明了一个整型数组data,此时这个数组中不包含任何元素,编译器仅会分配一块栈内存而不会分配堆内存给它。结构图如下所示:
第二行为整型数组data分配了可存放4个元素的堆内存空间,并把此内存空间的引用地址赋给data变量。结构图如下所示:
说明:图中的地址0x10000是假想地址,是为了方便理解内存分配。由于没有给数组各元素指定具体的值,所以使用了int类型的默认值0。数组元素的下标是从0开始的,所以第一个元素是data[0],第二个元素是data[1],以此类推。最后一个元素的下标是数组元素个数减1。
语法格式二:
数组类型[] 数组名称 = new 数组类型[元素个数];
这种声明方式一般是程序开发中最常用的方式。在声明的同时即分配一块内存空间,供数组使用。示例如下:
int[] data = new int[4];
说明:声明一个元素个数为4的整型数组data,同时开辟一块内存空间供其使用。
范例:ArrayDemo01.java
public class ArrayDemo01{ public static void main(String[] args){ int[] data = new int[4]; for(int i=0; i<4; i++){ System.out.println(data[i]); } } }
程序输出结果为:
上面第4行代码中,循环变量i的终值判断条件是i<4,这是硬编码的方式写的,当把数组的元素个数修改后,这里也要着相应的修改,否则程序代码就会有问题。为了让编译器自动获取数组的元素个数,数组提供了一个属性“.length”来实现。上面代码修改如下:
范例:ArrayDemo02.java
public class ArrayDemo02{ public static void main(String[] args){ int[] data = new int[4]; for(int i=0; i<data.length; i++){ System.out.println(data[i]); } } }
输出的结果不变,但代码的通用性要好很多。
5.1.2 数组初值
如果想直接在声明数组时就给数组赋初值,那么就可以利用大括号来完成。语法定义格式如下:
数据类型[] 数组名称 = {初值0,初值1,...,初值n};
大括号内的初值会依序指定给数组的第1,2,...,n+1个元素。此外,在声明数组时不需要将数组元素的个数指定,编译器会根据所给出的初值个数来判断数组的长度。
范例:ArrayDemo03.java
public class ArrayDemo03{ public static void main(String[] args){ int[] month = {5,2,10,6,4,8,1,9,11,3,7,12}; for(int i=0; i<month.length; i++){ System.out.print(month[i] + ", "); } } }
程序输出结果如下:
现在输出的数组元素是没有顺序的,如果想要顺序的输出数组元素,可以使用一些成熟的算法来实现。下以用冒泡排序和选择排序及JDK中提供的Arrays类来实现。
冒泡排序:一种简单的交换排序。基本思路是从头开始扫描待排序的元素。在扫描过程中依次对相邻元素进行比较,将值大的元素后移。每经过一趟排序后,最大的元素将会被移到末尾并记下该元素的位置。下一趟排序只需要比较到此位置为止,直到所有元素都比较完成。
一般来说,对n个元素进行冒泡排序,总共需要进行n-1轮循环。第一轮循环需要比较n-1次,第二轮循环需要比较n-2次,以次类推第i轮循环需要比较n-i次。
范例:ArrayDemo04.java
public class ArrayDemo04{ public static void main(String[] args){ int[] month = {5,2,10,6,4,8,1,9,11,3,7,12}; for(int x=0; x<month.length-1; x++){ for(int y=0; y<month.length-x-1; y++){ if(month[y] > month[y+1]){ int temp = month[y]; month[y] = month[y+1]; month[y+1] = temp; } } } for(int i=0; i<month.length; i++){ System.out.print(month[i] + ", "); } } }
程序输出结果如下:
选择排序:一种简单直观的排序算法。基本思路是从头开始扫描待排序的元素。在扫描过程中依次对后面的元素进行比较,将值小的元素前移。每经过一趟排序后,最小的元素将会被移到前面并记下该元素的位置。下一趟排序只需要从这个位置进行比较即可,直到所有元素都比较完成。
范例:ArrayDemo05.java
public class ArrayDemo05{ public static void main(String[] args){ int[] month = {5,2,10,6,4,8,1,9,11,3,7,12}; for(int x=0; x<month.length-1; x++){ for(int y=x+1; y<month.length; y++){ if(month[x] > month[y]){ int temp = month[x]; month[x] = month[y]; month[y] = temp; } } } for(int i=0; i<month.length; i++){ System.out.print(month[i] + ", "); } } }
程序输出结果如下:
JDK提供的数组Arrays类:
范例:ArrayDemo06.java
import java.util.Arrays; public class ArrayDemo06{ public static void main(String[] args){ int[] month = {5,2,10,6,4,8,1,9,11,3,7,12}; Arrays.sort(month); for(int i=0; i<month.length; i++){ System.out.print(month[i] + ", "); } } }
要想使用JDK提供的Arrays类,必须在程序的开头部分导入该类,该类位于java.util包中,使用import关键词来导入该类。程序输出结果如下:
从以上三种排序方式不难看出,使用Arrays类中的sort方法对数组进行排序是最简单的方式。
5.2 二维数组
一维数组一般用于处理简单的数据,对应实际开发中要处理数据库表数据时,一维数组就显得不足。因此Java提供了二维数组来实现这类需求。二维数组就相当于一张数据库表结构。
5.2.1 二维数组的声明
与一维数组类似,二维数组声明也有两种方式:
声明方式一:
数据类型[][] 数组名称; 数组名称 = new 数据类型[行数][列数];
“行数”是告诉编译器所声明的数组有多少行;“列数”是告诉编译器该数组有多少列。如:
int[][] data; //声明整型二维数组data data = new int[2][3]; //元素共有2行3列
声明方式二:
数据类型[][] 数组名称 = new 数据类型[行数][列数];
如:
int[][] data = new int[2][3]; //元素共有2行3列
上面声明的数组data可以保存的元素有2*3=6个元素。
在声明二维数组的同时,可以给该数组赋初值,格式如下:
int[][] data = { {第0行初值}, {第1行初值}, ... {第n行初值} };
示例如下:
int[][] month = { {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} };
5.2.2 二维数组行数和特定行的元素个数
要想获取二维数组的行数,可以通过数组名.length来获取。而获取特定行的元素个数需要指定行的下标,也就是通过数组名[行下标].length来获取。
5.2.3 二维数组的使用
范例:ArrayDemo07.java
public class ArrayDemo07{ public static void main(String[] args){ int[][] month = {{5,2,10},{6,4,8,1},{9,11,3,7,12}}; for(int x=0; x<month.length; x++){ for(int y=0; y<month[x].length; y++){ System.out.print(month[x][y] + ", "); } System.out.println(); } } }
程序运行结果如下:
5.3 多维数组
二维以上的数组就叫多维数组,这类数组一般处理起来比较复杂,因此直正开发中使用较少。定义方式和一维二维类似。三维声明为数据类型[][][] 数组名称,四维声明为数据类型[][][][] 数组名称......,以此类推。
5.3 方法
方法可以简化程序的结构,提高程序的复用性,达到程序模块化的目的。其实从第二章中最简单的Java程序中已经开始接触到方法了。比如Java程序的入口main()方法。
5.3.1 方法的定义
方法的下定义语法格式如下:
返回值类型 方法名称(类型 参数1, 类型 参数2, ..., 类型 参数n){ 程序语句块; return 表达式; }
说明:如果不需要传递参数到方法中,只要将括号写出,不必填写任何内容。如果方法没有返回值,则return语句可以省略。
5.3.2 方法的使用
5.3.2.1 不带参数且无返回值的方法使用
范例:MethodDemo01.java
import java.util.Arrays; public class MethodDemo01{ public static void main(String[] args){ int[] month = {5,2,10,6,4,8,1,9,11,3,7,12}; Arrays.sort(month); star(); for(int i=0; i<month.length; i++){ System.out.print(month[i] + ", "); } star(); } public static void star(){ System.out.println(); for(int x=0; x<40; x++){ System.out.print("*"); } System.out.println(); } }
程序运行结果如下:
****************************************
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
****************************************
分析:本例中包含了两个方法main()方法和star()方法。在main()方法中先调用了star()方法来输出40颗星形,然后程序再执行数组的排序,数组排序完成后,再一次调用了star()方法来输出40颗星形。
5.3.2.2 带参数且无返回值的方法使用
范例:MethodDemo02.java
import java.util.Arrays; public class MethodDemo02{ public static void main(String[] args){ int[] month = {5,2,10,6,4,8,1,9,11,3,7,12}; Arrays.sort(month); star(40); for(int i=0; i<month.length; i++){ System.out.print(month[i] + ", "); } star(40); } public static void star(int num){ System.out.println(); for(int x=0; x<num; x++){ System.out.print("*"); } System.out.println(); } }
程序运行结果如下:
****************************************
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
****************************************
分析:本例中包含了两个方法main()方法和带有参数star(int num)方法。在main()方法中先调用了star(40)方法来输出指定个数的颗星形,然后程序再执行数组的排序,数组排序完成后,再一次调用了star(40)方法来输出指定个数的颗星形。
5.3.2.3 带参数且有返回值的方法使用
范例:MethodDemo03.java
public class MethodDemo03{ public static void main(String[] args){ int sum = getArea(3, 5); System.out.println("3 * 5 = " + sum); } public static int add(int num1, int num2){ return num1 * num2; } }
程序运行结果如下:
3 * 5 = 18
5.3.3 方法重载
现有需求如下,要求获取任意两个整数之和。则程序代码编写如下:
范例:MethodDemo04.java
public class MethodDemo04{ public static void main(String[] args){ int sum = add(3, 5); System.out.println(sum); } public static int add(int num1, int num2){ return num1 + num2; } }
现需要发生了变化,除了获取任意两个整数之和外,还需要获取任意三个整数之和。那么程序代码修改如下:
范例:MethodDemo05.java
public class MethodDemo05{ public static void main(String[] args){ int sum = add1(3, 5); System.out.println(sum); sum = add2(2, 3, 4); System.out.println(sum); } public static int add1(int num1, int num2){ return num1 + num2; } public static int add2(int num1, int num2, int num3){ return num1 + num2 + num3; } }
上面代码看似没有问题,运行也没问题,但是这段代码真的好么?如果还需要获取四个整数的和,那么是不是还得编写一个add3()方法?既然都是做加法运算,能不能只用一个方法名称,然后传入不同的参数来实现这个需求?
可以的,Java中提供了方法重载来实现该功能。
方法重载就是在同一个类中允许同时存在一个以上的同名方法,只要它们参数个数或类型不同即可。因此上面程序代码修改如下:
范例:MethodDemo06.java
public class MethodDemo06{ public static void main(String[] args){ int sum = add(3, 5); System.out.println(sum); sum = add(2, 3, 4); System.out.println(sum); } public static int add(int num1, int num2){ return num1 + num2; } public static int add(int num1, int num2, int num3){ return num1 + num2 + num3; } }
方法重载的特点:
1)方法名称必须相同;
2)参数列表必须不同(包括参数个数,或参数类型不同,或参数顺序不同);
3)与返回值类型无关;
4)必须是同一个类中。