JAVA数组重点Master知识,以后肯定会用到的,可以Understand一下底层Principle。数组是指一组Data的集合,数组中的每个Data被称作元素。在数组中可以存放任意Type的元素,但同一个数组里存放的元素Type必须一致。

数组

数组定义格式:

数据类型[] 数组名(变量名) = new 数据类型[元素个数或数组长度];

Example:

public class ArrayDemo01 {

	public static void main(String[] args) {
		int[] x = new int[100];
	}
}

注意:数组定长,一但定义长度为100,在Usage时大小就是100了。不变量。

数组特点:定长、引用Type。

JVM

java程序Run时,操作系统会给jvmVirtual Machine分配一块内存。JVM又会将这块内存,进行划分管理。

JVM内存划分:JVM对自己的内存进行了划分,分成5个区域。

1、寄存器:内存和CPU之间。
2、本地方法栈:JVM调用操作系统中的功能。
3、方法和数据共享:运行时其class文件,进入的地方。
4、方法栈:所有的方法运行的时候,进入的内存。
5、堆:存储的是容器和对象。

Development人员主要关心:Method和Data共享、Method栈、堆。

数组内存划分

  1. 首先,运行class文件,所以先进入方法区。
  2. 运行main方法,在方法栈中运行,但是main用不了那么多,所以方法栈中会分配一块给main方法是用。
  3. 执行数组,一个容器,所以JVM在堆内存,开空间,存储数组容器。
  4. JVM会将该地址,给定义的数组变量arr(相当于arr引用了这个地址),所以数组是引用类型。
  5. 每次运行,JVM分配的地址是不同的。
  6. 当main方法运行完了,arr变量就没了,然后new int[3]也就没了 ,JVM垃圾回收机制,会自动帮我们回收,不用我们去处理了。

堆空间太大,怎么找到这个Container呢,所以每个数组,在内存中,都有自己的内存地址,也就是数组元素的首地址,第一个Data的地址。

注意:arr引用Type,保存的Data,实际上是内存中的地址。

数组元素的访问

数组是一个Container,Storage到数组中的每个元素,都有自己的自动编号/下标(专业名词:Indexing)。

访问数组Storage的元素,必须DependencyIndexing。

访问公式:数组名[Indexing]

public class ArrayDemo02 {

	public static void main(String[] args) {
		int[] arr = new int[3];
		System.out.println(arr[0]);
		System.out.println(arr[1]);
		System.out.println(arr[2]);
	}
}

一初始化时,数组里面就有了默认值。

注意:数组Indexing是从0开始的。当数组被成功Create后,数组中元素会被自动赋予一个默认值,根据元素Type的不同,默认初始化的值也是不一样的。

byte、short、int、long:默认值0

float、double:默认值0.0

char:默认值一个空字符(空格),即’\u0000’

boolean:默认值false

引用数据类型:null,表示变量不引用任何对象

数组的属性

数组的长度length:

Usage Method:数组名.length

public class ArrayDemo02 {

	public static void main(String[] args) {
		int[] arr = new int[3];
		System.out.println(arr[0]);
		System.out.println(arr[1]);
		System.out.println(arr[2]);
		System.out.println(arr.length);
	}
}

注意:length是intType,因此数组最大Indexing为:数组名.length-1

数组中最小的Indexing是0,最大的Indexing是“数组的长度-1”。在Java中,为了方便我们获得数组的长度,提供了一个length属性,在程序中可以通过“数组名.length”的方式来获得数组的长 度,即元素的个数。

数组初始化

  1. 在定义数组时只指定数组的长度,由系统自动为元素赋初值的方式称作动态初始化。

  2. 数组的静态初始化

    方式一:DataType[] 变量名 = new DataType[]{元素1,元素2,元素3…};

    方式二:DataType[] 变量名 = {元素1,元素2,元素3,…};

    public class ArrayDemo03 {
    
    	public static void main(String[] args) {
    		//定义方式一
    		int[] arr = new int[] {1,3,4,5};
    		System.out.println(arr.length);
    		//注意:new 后面的中括号中,不允许写任何内容,写了就Compile失败。
    		//ErrorExample:
    		//int[] arr = new int[4]{1,2,3,4};
    		
    		//定义方式二(这种比较简单,常用)
    		int[] arr2 = {1,2,3,4,};
    		//注意:最后一个逗号,会自动去掉
    		System.out.println(arr2.length);
    	}
    }

    注意:第3行Code千万不可写成int[] arr = new int[4]{1,2,3,4};,这样写Compile器会Error。原因在于Compile器会认为数组限定的元素个数[4]与实际Storage的元素{1,2,3,4}个数有可能不一致,存在一定的Safety隐患。

数组元素赋值

public class ArrayDemo04 {

	public static void main(String[] args) {
		//没有赋值的元素,都是默认值
		int[] arr = new int[3];
		arr[2] =5;
		System.out.println(arr[0]);
		System.out.println(arr[1]);
		System.out.println(arr[2]);
	}
}

注意:如果在Usage数组时,不想Usage这些默认初始值,也可以显式地为这些元素赋值,如上Code。

数组的遍历

遍历:通过Indexing的方式,将数组中的每个元素,分别Get出来。

public class ArrayDemo05 {

	public static void main(String[] args) {
		int[] arr = {1,2,4,52,4,3,6,};
		System.out.println(arr[0]);
		System.out.println(arr[1]);
		System.out.println(arr[2]);
		System.out.println(arr[3]);
		//......
		//如果有几千个,这样肯定不行,索引是依次加1的,因此可以用到循环来变量。
		
		//for:知道循环次数,计数器思想
		//while:不确定循环次数。
		for(int i=0;i<arr.length;i++) {
			System.out.println(arr[i]);
		}
	}
}

输出结果:

1
2
4
52
1
2
4
52
4
3
6

注意:

//for:知道循环次数,Counter思想

//while:不确定循环次数。

会自动去掉最后一个逗号。

数组中常见异常

  1. 数组索引越界异常

    public class ArrayError {
    
    	public static void main(String[] args) {
    		int[] arr = {1,2,4,};
    		//1、数组Indexing越界异常
    		System.out.println(arr[3]);
    		System.out.println(arr[-2]);
    	}
    }

    输出结果,Compile时不出错,Run时,Error提示信息:

    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:

    Error原因:Indexing越界、Indexing为负数。

  2. 空指针异常

    public class ArrayError {
    
    	public static void main(String[] args) {
    		//2、空指针异常
    		int[] arr2 = {2,345,4};
    		System.out.println(arr2[2]);;
    		arr2 = null;//arr2不在保持数组的地址了
    		System.out.println(arr2[2]);
    	}
    }

    空指针内存Run说明:

    步骤1:int[] arr2 = {1,5,8},存在于栈中
    步骤2:同时在堆中开辟一块内存空间StorageData,并分配一个地址,如图右边。
    步骤3:arr2变量,引用Execute该Storage空间地址。
    
    上面3步是正常情况。
    
    步骤4:当Executearr2=null时,arr2引用就没有了指向的空间地址。
    步骤5:打印的数组的时候就会出现空指针异常了。

    输出结果:Error提示信息

    Exception in thread "main" java.lang.NullPointerException

    Error原因:数组变量为null

    注意:内存地址只能给一次,不能给第2次地址。因为为null空指向断了,JVM可能已经将堆地址内存释放掉了,不能再给回来。

数组获取最值

Get最值的Principle思想:找到数组中的最大值或最小值,然后做比较。

最大值或最小值比较思想:将最大值放到一个变量中,赋值为第一个元素,每次将这个值与其他元素比较,将大的给这个值,最后这个就是最大值。最小值同理。

public class ArrayDemo05 {
	public static void main(String[] args) {
		int[] arr = { 4, 1, 6, 3, 9, 8 }; // 定义一个数组
        int max = arr[0]; // 定义变量max用于记住最大数,首先假设第一个元素为最大值
		// 下面通过一个for循环遍历数组中的元素
		for (int x = 1; x < arr.length; x++) {
			if (arr[x] > max) { // 比较 arr[x]的值是否大于max
				max = arr[x]; // 条件成立,将arr[x]的值赋给max
			}
		}
		System.out.println("max=" + max); // 打印最大值
	}
}

说明:

1、定义了一个临时变量max,用于记住数组的最大值。通过for 循环获取数组中的最大值,赋值给max变量。
2、首先假设数组中第一个元素arr[0]为最大值。
3、使用for循环对数组进行遍历,在遍历的过程中只要遇到比max值还大的元素,就将该元素赋值给max。
4、这样一来,变量max就能够在循环结束时记住数组中的最大值。

需要注意的是,在for循环中的变量i是从1开始的,这样写的原因是程序已经假设第一个元素为最大值,for循环中只需要从第二个元素开始比较,从而提高程序的Run效率。

二维数组

二维数组的定义有很多方式,几种常见的方式。

  1. 第一种方式:

    int[][] arr = new int[3][4];

    上面的Code相当于定义了一个3*4的二维数组,即二维数组的长度为3,二维数组中的每个元素又是一个长度为4的数组,接下来通过一个图来表示这种情况,如下图所示。

数组

  1. 第二种方式:

    int[][] arr = new int[3][];

    第二种方式和第一种类似,只是数组中每个元素的长度不确定.

  2. 第三种方式:

    int[][] arr = {{1,2},{3,4,5,6},{7,8,9}};

    上面的二维数组中定义了三个元素,这三个元素都是数组,分别为{1,2}、{3,4,5,6}、{7,8,9}。

对二维数组中元素的访问也是通过角标的方式,如需访问二维数组中第一个元素数组的第二个元素,具体Code如下:

arr[0][1];

操作二维数组时,经常需要Get数组中元素的值。

public class TwoArrayDemo {

public static void main(String[] args) {
	//二维数组创建方式
	//方式一
	int[][] arr = new int[2][3];
	//方式二
	int[][] arr2 = new int[2][];
	arr2[0] = new int[5];
	arr2[1] = new int[1];
	//方式三
	int[][] arr3 = {{2,4,5},{1,2},{6,3,5,5}};
	//这种方式最简单,最常用。
 }
}

二维数组内存分配:

public class TwoArrayDemo {

	public static void main(String[] args) {
		int[][] arr3 = {{2,4,5},{1,2},{6,3,5,5}};
        
		//二维数组的访问
		System.out.println(arr3[2][2]);
        
		//二维数组的遍历
		for(int i=0;i<arr3.length;i++) {
			for(int j=0;j<arr3[i].length;j++) {
				System.out.print(arr3[i][j]);
			}
			System.out.println();
		}
	}
}