JAVA学习day05 javase基础语法——数组概述和定义格式说明
1.1 数组的概念
数组是存储同一种数据类型多个元素的集合。也可以看成一个容器。 数组既可以存储基本数据类型,也可以存储引用数据类型,但在同一个数组中,存储的数据类型必须一致。
定义格式: 数据类型 [ ] 数组名 = new 数据类型 [ 元素个数或数组长度]; 或 数据类型 数组名 [ ] = new 数据类型[元素个数或数组长度];
int[] arr = new int[2]; int arr [] = new int [3];上述语句就相当于在内存中定义了2个 int 类型的变量,第一个变量的名称为arr[ 0 ];第二个变量就是arr[ 1 ]; 要注意数组的索引是从 0 开始的,并非从1开始。
1.2 数组的初始化
Java中的数组必须先初始化,然后才能用。所谓的初始化,就是给数组中的元素分配内存空间,并为每个数组元素赋值。 初始化的分类有动态初始化 : 只指定长度,由系统给出初始化值;静态初始化 :给出初始化值,由系统判断长度。 下面是两种初始化的格式 :
//动态初始化 int[] arr = new int [100]; //静态初始化 int[] arr1 = {0,1,2,3,4,5};下面通过一个案例介绍如何进行定义数组及访问数组中的元素:
package org.westos.demo3; public class ArrayDemo { public static void main(String[] args) { //动态初始化数组 int[] arr = new int[5]; arr[0] = 1; arr[1] = 2; arr[2] = 3; arr[3] = 4; //访问数组中的第四个元素 System.out.println("arr[0]="+arr[0]); System.out.println("arr[1]="+arr[1]); System.out.println("arr[2]="+arr[2]); System.out.println("arr[3]="+arr[3]); System.out.println("arr[4]="+arr[4]); } }运行如下图所示: 图 1-1 运行结果截图
我们看到没被赋值的arr[ 4 ] 会被系统赋一个为0的初值。
1.3 Java中的内存分配以及堆和栈的区别
(1)栈:栈存放的是局部变量,局部变量是在方法中定义或声明的; (2)堆:堆中存放的是所有 new 出来的对象;特点: a:每一个 new 出来的对象都会给其分配一个地址值。 b:每个变量都有一个默认的初值:
byte,short,int,long 初值为0 ; float,double 初值为0.0 ; char 初值是一个空字符’ \u000’ ; boolean 初值为false ; 引用数据类型为null ; c:变量使用完毕后就变成了垃圾,等待垃圾回收器对其回收。 (3)方法区:用于存储已被JVM加载的类信息 、常量 、静态变量 。 (4)本地方法栈:(和系统相关)。 (5)寄存器:cpu 使用。
下面我们通过几个案例分析数组的内存图解: (1)定义一个数组,输出数组名称和数组中的元素值,给数组赋值,再次输出数组名称和数组中的元素值。 代码:
package org.westos.demo3; public class ArrayDemo1 { public static void main(String[] args) { int[] arr = new int[3]; System.out.println("arr[0]="+arr[0]); System.out.println("arr[1]="+arr[1]); System.out.println("arr[2]="+arr[2]); arr[0] = 1; arr[1] = 2; arr[2] = 3; System.out.println("-----------------"); System.out.println("arr[0]="+arr[0]); System.out.println("arr[1]="+arr[1]); System.out.println("arr[2]="+arr[2]); } }运行结果: 图 1-2 运行结果截图 内存图: 图 1-3 内存图
1.4 数组的遍历 在操作数组时,经常需要依次访问数组中的每个元素,这种操作称作数组的遍历。接下来通过一个案例来学习如何使用for循环来遍历数组,如下所示。
package org.westos.demo2; public class ArrayDemo { public static void main(String[] args) { int[] arr = {1,2,3,4,6,9,45,52,4,65}; for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]+"\t"); } } }运行结果: 图 1-4 运行结果截图
上述代码中,用一个 for 循环定义一个变量 i 来作为数组的索引依次访问数组中的元素,循环打印出数组中的每个元素。
案例:在操作数组时,经常需要获取数组中元素的最值。接下来通过一个案例来演示如何获取数组中元素的最大值,如下代码所示:
package org.westos.demo2; public class ArrayMaxDemo { public static void main(String[] args) { int[] arr = {1,2,3,6,7,9}; int max = arr[0]; for (int i = 1; i < arr.length; i++) { if(arr[i] > max ){ max = arr[i]; } } System.out.println("数组的最大值是:"+max); } }运行结果如下: 图 1-5 运行结果截图 上述代码中,首先定义一个数组arr,静态初始化数组后,数组中有六个元素,然后我们假设arr[ 0 ]作为数组中的最大值,再利用一个 for 循环遍历数组中的元素和这个arr [ 0 ]进行比较,如果遍历的这个元素大于我们赋的初值,就把这个元素作为最大值和接下来的数组中其他元素比较,直到数组遍历完,得出最大值的结果。
1.5 二维数组
● 定义方式: (1)int [ ][ ] arr = new int [ 2 ][ 3 ]; (2)int [ ][ ] arr = new int [ 3 ][ ]; (3)int[ ][ ] arr = {{1,2},{3},{4,5},{6,7,9}};
● 获取二维数组中的值和二位数组的遍历 通过下面的一段代码来看:
package org.westos.demo2; public class ArrayDemo2 { public static void main(String[] args) { int[][] arr = new int [2][]; int[] arr1 = {1,2,3}; int[] arr2 = {4,5,6}; arr[0] = arr1; arr[1] = arr2; for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr[i].length; j++) { System.out.print(arr[i][j]+"\t"); } System.out.println(); } } }来看上面的代码,其实获取二维数组的值和一维数组是相似的,只不过比一维数组多了个索引,二维数组的本质就是在一个数组中再存储了若干个一维数组,二维数组的遍历也是一样,在一维数组遍历的基础上再加一个for循环,两个for循环嵌套就能遍历出二维数组了。
运行结果: 图 1-6 运行结果截图
二维数组的内存图
● 二维数组案例练习: (1) 打印杨辉三角形(行数可以键盘录入) 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1
import java.util.Scanner; public class YangHuiTriangle { public static void main(String[] args) { System.out.println("请输入杨辉三角的行数:"); Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int[][] arr = new int[n][n]; //1.先把第一行和最后一行的元素给赋值1,打印看一下形状对不对 for (int i = 0; i < arr.length; i++) { for (int j = 0; j <= i; j++) { arr[i][0] = 1; arr[i][i] = 1; //System.out.print(arr[i][j]+"\t"); } } //2.分析元素之间的关系知道,除了1之外,别的元素的值都是等于上行的元素的值加上上一行前一列的值。 for (int i = 2; i < arr.length; i++) { for (int j = 1; j <= i; j++) { arr[i][j] = arr[i-1][j-1] + arr[i-1][j]; //System.out.print(arr[i][j]+"\t"); } // System.out.println(); } //3. 最后打印输出杨辉三角 for (int i = 0; i < arr.length; i++) { for (int j = 0; j <= i ; j++) { System.out.print(arr[i][j]+"\t"); } System.out.println(); } } }运行结果: 图 1-7 运行结果截图
1.6 数组的逆序
案例:定义一个数组,把数组逆序输出; 注意:逆序并非反向遍历输出。
public class ArrayReverseDemo { public static void main(String [] args){ //数组的逆序思想 //注意:不等于数组反向遍历输出 int[] array = {0,1,2,3,4,5,6,7,8,9}; int max = array.length-1; int min = 0; int temp; for (int i = 0; i < array.length; i++) { if (max > min ){ temp = array[max]; array[max] = array[min]; array[min] = temp; } max--; min++; System.out.print(array[i]+"\t"); } } }◆ 数组的逆序趋势就是把数组中最大的元素和最小的与元素给一个索引max和min,然后交换这两个数组元素的值,再进行一个max- -,min++;循环在max等于min的上一次终止,数组的逆序就完成了。 运行结果: 图 1-8 运行结果截图
1.7递归
递归概述: 方法定义中调用方法本身的现象
递归注意事项: (1)要有出口,否则就是死递归; (2)次数不能太多,否则就内存溢出。
案例:不死神兔问题(菲波那切数列):有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少? 由此可见兔子对象的数据是:1 , 1 , 2 , 3 , 5 , 8 …
import java.util.Scanner; public class RecursiveDemo { public static void main(String[] args) { System.out.println("请输入月份查看有多少对兔子:"); Scanner sc = new Scanner(System.in); int month = sc.nextInt(); int num = rabbit(month); System.out.println("有"+num+"对兔子"); } public static int rabbit(int n){ if(n == 1 || n == 2){ return 1; }else{ return rabbit(n-1)+rabbit(n-2); } } }运行结果: 图 1-9 运行结果截图