Java从入门到放弃05—数组/Java中的内存分配/栈/堆
1.概念
- 数组是存储同一种数据类型多个元素的集合。可以将数组看成是一个容器。
- 数组既可以存储基本数据类型,也可以存储引用数据类型。
2.定义格式及数组的初始化
- Java中的数组必须先初始化,才能使用。初始化就是为数组中的数组元素分配内存空间,并为数组的每个元素赋值。
- 数组的初始化方式有两种:动态初始化/静态初始化。(注:两种方式每次只能使用一种,不可以动静结合。)下面以程序说明两种方式的不同:
class ArrayPractice01{
public static void main(String[] args){
int[] arr1=new int[3];//动态初始化:只定义数组的长度,由系统赋默认值。数组创建好后,由系统分配索引脚标,从0开始到数组长度-1.
int num=arr1[2];//取出数组中的元素/注意打印和取出的区别。
System.out.println("数组arr1中索引脚标为2的元素为"+arr1[2]);//打印数组中索引脚标为2的元素
int[] arr2={1,2,3,4,5};//静态初始化:为数组赋值,由系统计算数组长度。
int length=arr2.length;//数组的长度属性
System.out.println("数组arr2的长度是"+length);
}
}
运行结果:数组arr1中索引脚标为2的元素为0
数组arr2的长度是5
- 常见数组异常
a.空指针异常(原因:数组已经不在指向堆内存了。而你还用数组名去访问元素。)
class ArrayPractice02{
public static void main(String[] args){
int[] arr={10,20};
arr=null;//人为置空
int length=arr.length;
System.out.println(length);
}
}
运行结果:NullPointerException (翻译:空指针异常)
b.数组脚标越界异常(原因:你访问了不存在的索引。)
class ArrayPractice03{
public static void main(String[] args){
int[] arr=new int[5];
int num=arr[arr.length];//数组中的最后一个元素索引=数组长度-1,因此该程序会报错
System.out,println(num);
}
}
运行结果:ArrayIndexOutOfBoundsException 数组角标越界异常
3.Java中的内存分配以及栈和堆的区别
-
栈:存放局部变量。(局部变量:在方法定义中或者方法声明上的变量都是局部变量)
-
堆:存放所有new出来的东西
a.每一个new出的东西都会在堆中分配到一个地址值
b.不同类型的变量都有对应的默认值
~~~
byte/short/int/long ------- 0
float/double ------- 0.0
char ------- ‘\u0000’
boolean ------- false
引用数据类型 ------- null
~~~c.地址值和使用完毕后就变成了垃圾,等待Java的回收算法对其回收
-
方法区:(面向对象部分讲解)
-
本地方法区:(和系统相关)
-
寄存器(CPU使用)
-
由三个数组只引用两个地址值的程序为例,具体说明内存分配过程:
class ArrayPractice04{//1.方法区生成ArrayPractice04.class文件 public static void main(String[] args){//2.栈开始执行main{} int[] arr1=new int[3];//3.由于new了一个新数组,因此堆为arr1分配内存空间,为数组赋默认值0,并返回地址值,如0x0001。 arr1[0]=10;//4a.根据地址值,对arr1[0]重新赋值,将默认值覆盖。 arr1[1]=20;//4b.根据地址值,对arr1[1]重新赋值,将默认值覆盖。 int[] arr2=new int[3];//5.由于new了一个新数组,因此堆为arr2重新分配内存空间,为数组赋默认值0,并返回地址值,如0x0002。 arr2[1]=34;//5a.根据地址值,对arr2[1]重新赋值,将默认值覆盖。 arr2[2]=89;//5b.根据地址值,对arr2[2]重新赋值,将默认值覆盖。 int[] arr3=arr1;//6.没有new,因此堆不会重新分配内存空间,将数组arr1的地址值赋值给数组arr3,此时arr3与arr1元素相同。 arr3[0]=78;//7.由于arr3和arr1引用同一个地址值,对arr3[0]重新赋值会将arr1[0]原先的值覆盖掉,因此导致arr1[0]的值也发生改变。 arr3[1]=28;//同理,arr3[1]的重新赋值会导致arr1[1]发生改变。 arr3[2]=99;//同理,arr3[2]的重新赋值会导致arr1[2]发生改变。 System.out.println("arr1[0]="+arr1[0]);//78 System.out.println("arr1[1]="+arr1[1]);//28 System.out.println("arr1[2]="+arr1[2]);//99 System.out.println("arr2[0]="+arr2[0]);//0 System.out.println("arr2[1]="+arr2[1]);//34 System.out.println("arr2[2]="+arr2[2]);//89 System.out.println("arr3[0]="+arr3[0]);//78 System.out.println("arr3[1]="+arr3[1]);//28 System.out.println("arr3[2]="+arr3[2]);//99 } } 运行结果: arr1[0]=78 arr1[1]=28 arr1[2]=99 arr2[0]=0 arr2[1]=34 arr2[2]=89 arr3[0]=78 arr3[1]=28 arr3[2]=99
4.数组的操作
01 遍历(依次输出数组中的每个元素)
class ArrayPractice05{ public static void main(String[] args){ int[] arr={10,20,30,40,50}; System.out.println("------正向遍历------"); for(int i=0;i<=arr.length-1;i++){ System.out.print(arr[i]+"\t"); } System.out,println(); System.out.println("------反向遍历------"); for(int j=arr.length-1;j>=0;j--){ System.out.print(arr[j]+"\t"); } } } 运行结果:---------- 运行 ---------- ------正向遍历------ 10 20 30 40 50 ------反向遍历------ 50 40 30 20 10 输出完成 (耗时 0 秒) - 正常终止
02 获取最值
class ArrayPractice06{ public static void main(String[] args){ int[] arr={32,45,87,23,65}; int max=arr[0]; for(int i=1;i<=arr.length-1;i++){ max=max>arr[i]?max:arr[i]; } System.out.println("数组arr中最大的元素是"+max); } } 运行结果:数组arr中最大的元素是87
03 数组元素反转(将数组中的元素进行对调,按倒序输出)
class ArrayPractice07{ public static void main(String[] args){ int[] arr={109,89,40,34,57,99}; int t=0; for(int i=0,j=arr.length-1;i<j;i++,j--){ t=arr[i]; arr[i]=arr[arr.length-1-i]; arr[arr.length-1-i]=t; } for(int j=0;j<=arr.length-1;j++){ System.out.print(arr[j]+"\t"); } } } 运行结果:99 57 34 40 89 109
04 查表法
a.根据索引查元素
import java.util.Scanner; class ArrayPractice08{ public static void main(String[] args){ String[] str={"星期一","星期二","星期三","星期四","星期五","星期六","星期日"}; Scanner sc=new Scanner(System.in); System.out.println("请在1---7之间选择你想输入的索引"); int index=sc.nextInt(); String weekname=getWeekname(index,str); System.out.println(weekname); } public static String getWeekname(int index,String str[]){ if(1<=index&&index>=7){ String weekname=str[index-1]; return weekname; }else{ return "输入的索引有误"; } } }
b.根据元素查索引
import java.util.Scanner; public class ArrayDemo10 { public static void main(String[] args){ String[] str={"星期一","星期二","星期三","星期四","星期五","星期六","星期日"}; Scanner Wname=new Scanner(System.in); System.out.println("请输入关键字/例:星期一"); String name=Wname.nextLine();//String类型数据的录入程序格式 int index = getIndex(name, str); System.out.println("您查找的索引号为:"+index); } public static int getIndex(String name,String[] str){//注意返回值类型要与方法中定义的返回值类型保持一致 for(int i=0;i<=str.length-1;i++){ if(name.equals(str[i])){//String类型数据之间比较相等的语句**.equals(***) return i; } } return -1;//通常用-1表示未查找到 } }