详解Java数组的一维和二维讲解和内存显示图
作者:tq02
一.数组的认识
在C语言里,我们也曾学习过数组,数组是什么?数组就相当于一个容器,存放相同类型数据的容器。而数组的本质上就是让我们能 "批量" 创建相同类型的变量。
注:容器是固定了大小的,不可改变的那种,例如:矿泉水瓶子、汽油罐、衣柜等容量大小不一的容器。
二.一维数组的用法
2.1 数组的创建
数组的初始化有2种形式
1、静态初始化(固定内容)
2、动态初始化(固定长度)
静态初始化:指在数组声明的同时,直接给数组引用赋值 ,不需要申明长度数据类型[ ]数组名称 = new 数据类型 [ ]{ 初始化数据 };
示例:int[ ]arr = new int[ ]{1, 2, 3};
省略方式:数据类型 [ ] 数组名称 = { 初始化数据 }; 示例:int [ ]arr = {1, 2, 3};
注:省略方式不允许先声明后赋值,只能声明同时直接赋值。
例如:int [ ]arr3; arr3 = {} //编译出错
动态初始化:指数组声明和数组引用赋值分开。根据数组定义方式的不同,又分为两种。
第一种:直接引用相同数组进行赋值。
例如:int[ ] arr=arr;直接将数组arr赋值给了arr;注:一定得相同类型的数组
第二种:数据类型 [ ]数组名称 = new 数据类型 [数组长度];
例如:int [ ]arr1 = int[10]; int arr1[0] = 0;
2.2数组的使用
每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引 (index)
,可以通过数组的索引访问到数组中的元素。 数组的长度属性: 每个数组都具有长度,而且是固定的,Java中赋予了数组的一个属性,可以获取到数组的长度,语句为:数组名。length,属性length的执行结果是数组的长度,int类型结果。由次可以推断出,数组的最大索引值为:数组名。length-1。
public static void main(String[] args) { int[] arr = new int[]{1,2,3,4,5}; //打印数组的长度,输出结果是5 System.out.println(arr.length); //打印对应数组的值,输出结果为1 System.out.println(arr[0]); }
2.3数组内存原理
在Java中,内存是非常非常重要的,作用:运行程序。我们编写的程序都是存放在硬盘当中的,而在硬盘里的程序是不会运行的,必须得在内存当中才能运行,运行完毕后会清空内存。 Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。
2.3.1Java虚拟机内存划分
Java为了提高效率,把内存进行了划分,从而使每一片区域都有特点的处理数据方式和内存管理方式。
jvm的内存划分:
区域名称 | 作用 |
寄存器 | 给CPU使用,和我们开发无关 |
本地方法栈 | JVM在使用操作系统功能的时候使用,和我们开发无关 |
方法区 | 存储可以运行的class文件 |
堆内存 | 存储对象或者数组,new来创建的,都存储在堆内存 |
方法栈 | 方法运行时使用的内存,比如main方法运行,进入方法栈中执行 |
此处我们不详细讲解,只讲解与数组有关的堆区间。
1.栈(Stack): 存放的都是方法中的局部变量。方法的运行一定要在栈当中运行局部变量:方法的参数,或者是方法几内部的变量 作用域: 一旦超出作用域,立刻从栈内存当中消失
2.堆(Heap) : 凡是new出来的东西都在堆中
2.3.2数组内存示例图
在图中我们可以看见,栈区可以有堆区,其实不是这样理解的,而是可以通过栈区而去访问堆区,
个人理解:数组变量名就是一个遥控器,可以控制堆区。
三.二维数组的认识
二维数组本质上也就是一维数组, 只不过每个元素又是一个一维数组
二维数组的四种不同形式的定义方式:
定义二维数组:int[][] array1 = new int[10][10];
定义二维数组(简洁版):int array2[][] = new int[10][10];
定义二维数组并且初始化:int array3[][] = { { 1, 1, 1 }, { 2, 2, 2 } };
定义二维数组并且初始化(简洁版)int array4[][] = new int[][] { { 1, 1, 1 }, { 2, 2, 2 } };
其实仔细一看。我们可以看见以上的定义方式和一维数组十分相似。
二维数组存储的相当于一维数组的集合。
图片例如:
二维数组array3 拥有array3[0]和array3[1]两个一维数组,其实道理和一维数组一样,只不过拥有的不再是元素,而是数组。想象一下套娃,便懂了。
注:只定义二维数组时,可以不写第二个下标,但一定需要定义第一个下标,实际就是定义有几个一维数组。
四.数组作为方法参数和返回值
将数组传递到方法当中。有没有想过,这是值传递,还是地址传递呢?
public static void main(String[] args) { int[] arr = {1, 2, 3}; func(arr); System.out.println("arr[0] = " + arr[0]); } public static void func(int[] a) { a[0] = 10; System.out.println("a[0] = " + a[0]); } // 执行结果 a[0] = 10 arr[0] = 10
我们可以发现数组传递过去之后,程序结束,数组值发生了改变,那么这是地址传递吗?事实上,并不是的。但是我们得注意,此时此刻我们这并不是传地址,而是传引用。
原理图:
解释:相当于从一个控制器(arr)变成了两个控制器(arr,a),这两个指向同一个堆,都可以对其修改。
但是是否存在传引用之后,却无法改变实参的值?存在的,new可以创造出一个新的堆空间,从而与之前的数组分道扬镳。
例如:
重点: arr数组值为1,2,3;传引用之后,a的数组值也为1,2,3;也就是说,arr==a;但是重新new出一个堆空间之后,a控制的堆不再是arr控制的堆,因此也无法改变arr数组了
五.Java常用API
API,你先当作一个方法库一样理解,有了API,我们可以更加快速的操作数组。
5.1输出数组
Arrays.toString()
int[] array = { 1, 2, 3 }; System.out.println(Arrays.toString(array)); //输出【1,2,3】
5.2数组转集合
Arrays.asList()
String[] array2 = {"a", "b", "c", "d"}; System.out.println(array2); List list = new ArrayList(Arrays.asList(array2)); System.out.println(list); // [a, b, c, d] list.add("GG"); System.out.println(list); // [a, b, c, d, GG]
5.3数组中是否包含某个值 Arrays.asList().contains()
String[] array = { "a", "b", "c", "d", "e" }; boolean isEle = Arrays.asList(array).contains("a"); System.out.println(isEle);
5.4数组排序Arrays.sort()
int[] array = { 3, 1, 2 }; System.out.println(Arrays.sort(array)); //输出:1,2,3
5.5数组二分查找Arrays.binarySearch()
int[] array = { 1,2,4,5,3,7,8 }; System.out.println(Arrays.binarySearch(array,5)); //输出4
以上并不是全部,只是列举了一些常用的类方法。
总结
数组的重点在于了解内存存储的数据,还有如何使用数组的数据,如何快捷使用对应的类方法。
到此这篇关于详解Java数组的一维和二维讲解和内存显示图的文章就介绍到这了,更多相关Java一维二维数组和内存显示图内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!