深化Java基础之——数组与内存控制
2017-05-08 00:25
309 查看
作为一个程序猿,大家对数组一定不陌生。平时使用的也比较多,但是往往越简单的东西,可能越会容易忽略一些细节。
下面是对数组相关知识的一个学习总结,如有不对的地方,欢迎来指正。
Java数组的初始化有两种方式:
静态初始化:由程序员在定义数组时,显示的指定每个元素的值,数组长度由系统决定
动态初始化:程序员直接指定数组的长度,由系统为数组元素分配初始值
动态初始化,系统分配元素初始值规则:
基本类型中的整数类型(byte, int, short, long):初始化为0;
基本类型中的浮点类型(float, double):初始化为0.0;
基本类型中的字符类型(char):初始化为'\u0000';
基本类型中的布尔类型(boolean):初始化为false;
引用类型(类、接口、数组):初始化为null;
数组变量只是一个引用类型的变量,不是数组本身,而是指向堆内存中的数组对象,通过下面这个图更清楚的了解一下数组的内存分配
上述的三个数组初始化完成之后,长度就被分别固定为2,3,4,不可改变。但是这里会有一个数组变量引用的改变,造成数组长度可改变的假象。
上述代码的执行结果为:str数组长度为:3
str3数组长度为:3
JVM
看起来好像是str和str3数组的长度都被改变了,那么内存中真正发生了什么事情呢?请看下面的图:
当执行完前面两行数组变量赋值后,str,str3数组引用变量都指向了原来的str2数组,堆内存中的其他两个数组对象会被当做垃圾对象回收掉。
所以对三个数组变量的操作,实际上都是操作的同一个数组对象(这里有点类似于C/C++中的指针),所以数组中第二个元素也被替换成"JVM"。
这里就产生了数组初始化后长度发生改变的假象,实际上是指向了其他数组对象,原来数组对象长度并没有改变。
对于数组变量和数组对象这里一定要区分清楚,数组变量通常是存储在栈内存的,类似于C语言中的指针,真正意义上的数组初始化,就是在堆中为数组对象分配内存空间,初始化之后就变成了一个有效的数组对象,只要一个数组变量指向这个有效数组对象,程序中便可使用该数组。通过如下代码来理解一下:
代码第5行并没有对temp进行初始化,而是在第9行,让其指向了一个有效的数组对象,这时nums和temp两个变量指向的是同一块内存,这样便可以使用temp数组。
关于引用数组的初始化在下面的没有多维数组中顺便总结。
对于nums可以只初始化最左边的维数,nums = new int[4][],这些元素还要进一步初始化,让这4个int[] 型元素分别指向4个有效的数组对象,看如下例子。
注释其实写的比较清楚了,为了更深刻的理解,结合代码来看下面的内存分配图:
因为是a数组元素是引用类型,所以系统初始化为null,前两个元素在5、6行又分别初始化,所以指向了其他的内存空间。
通过上面的分析可以看出,多维数组的本质依然是一维数组,当然一维数组的元素也可以是二维数组,这样就是三维数组,以此类推。
在Java程序中使用数组,应多从内存控制的角度来把握程序。
下面是对数组相关知识的一个学习总结,如有不对的地方,欢迎来指正。
数组的初始化
1、Java数组是静态的
Java数组是静态的,只有在初始化过后才能使用,而Java数组一旦进行初始化之后,其长度就固定了,不可再改变。Java数组的初始化有两种方式:
静态初始化:由程序员在定义数组时,显示的指定每个元素的值,数组长度由系统决定
动态初始化:程序员直接指定数组的长度,由系统为数组元素分配初始值
动态初始化,系统分配元素初始值规则:
基本类型中的整数类型(byte, int, short, long):初始化为0;
基本类型中的浮点类型(float, double):初始化为0.0;
基本类型中的字符类型(char):初始化为'\u0000';
基本类型中的布尔类型(boolean):初始化为false;
引用类型(类、接口、数组):初始化为null;
//第一种静态初始化方式,长度为2 String[] str = new String{"java基础","数组初始化"}; //第二种静态初始化方式,长度为3 String[] str2 = {"静态","内存结构","java"}; //动态初始化方式,长度为4 String[] str3 = new String[4]; //Java语言允许通过length方法获取数组的长度 System.out.println("str数组长度为:" + str.length); System.out.println("str2数组长度为:" + str2.length); System.out.println("str3数组长度为:" + str3.length);
数组变量只是一个引用类型的变量,不是数组本身,而是指向堆内存中的数组对象,通过下面这个图更清楚的了解一下数组的内存分配
上述的三个数组初始化完成之后,长度就被分别固定为2,3,4,不可改变。但是这里会有一个数组变量引用的改变,造成数组长度可改变的假象。
str = str2; str3 = str2; System.out.println("str数组长度为:" + str.length); System.out.println("str3数组长度为:" + str3.length); //改变str3中的一个元素值 str3[1] = "JVM"; System.out.println(str2[1]);
上述代码的执行结果为:str数组长度为:3
str3数组长度为:3
JVM
看起来好像是str和str3数组的长度都被改变了,那么内存中真正发生了什么事情呢?请看下面的图:
当执行完前面两行数组变量赋值后,str,str3数组引用变量都指向了原来的str2数组,堆内存中的其他两个数组对象会被当做垃圾对象回收掉。
所以对三个数组变量的操作,实际上都是操作的同一个数组对象(这里有点类似于C/C++中的指针),所以数组中第二个元素也被替换成"JVM"。
这里就产生了数组初始化后长度发生改变的假象,实际上是指向了其他数组对象,原来数组对象长度并没有改变。
2.数组一定要初始化吗?
通过上面的例子,大家应该明白了数组在内存中的分配机制,那么对于这个问题也就好理解了。对于数组变量和数组对象这里一定要区分清楚,数组变量通常是存储在栈内存的,类似于C语言中的指针,真正意义上的数组初始化,就是在堆中为数组对象分配内存空间,初始化之后就变成了一个有效的数组对象,只要一个数组变量指向这个有效数组对象,程序中便可使用该数组。通过如下代码来理解一下:
1 public static void main(String[] args){ 2 //静态初始化一个int类型数组 3 int[] nums = new int{1, 2, 3, 4}; 4 //定义一个int类型的数组变量,不初始化 5 int[] temp; 6 //输出nums数组中一个元素 7 System.out.println("nums数组第二个元素为:" + nums[1]); 8 //让temp数组变量指向nums所引用的数组对象 9 temp = nums; 10 //更改temp数组的第二个值,这里已经可以使用temp数组 11 temp[1] = 5; 12 //nums数组的第二个元素值为5 13 System.out.println("nums数组第二个元素为:" + nums[1]); 14 }
代码第5行并没有对temp进行初始化,而是在第9行,让其指向了一个有效的数组对象,这时nums和temp两个变量指向的是同一块内存,这样便可以使用temp数组。
关于引用数组的初始化在下面的没有多维数组中顺便总结。
使用数组
没有多维数组
Java允许将多维数组当做一维数组处理。对于int[][] nums 类型的数组,就是元素类型为int[] 的一维数组,nums数组的每个int[] 型元素再指向内存中其他的int型数据。对于nums可以只初始化最左边的维数,nums = new int[4][],这些元素还要进一步初始化,让这4个int[] 型元素分别指向4个有效的数组对象,看如下例子。
1 int[][] a = new int[4][]; 2 //4个引用类型元素,所以会输出4个null 3 System.out.println(Arrays.toString(a)); 4 //初始化a数组前两个元素 5 a[0] = new int[]{1, 2}; 6 a[1] = new int[]{3, 4, 5}; 7 //输出a数组第二个元素指向的内存空间的第3个元素 8 System.out.println(a[1][2]);
注释其实写的比较清楚了,为了更深刻的理解,结合代码来看下面的内存分配图:
因为是a数组元素是引用类型,所以系统初始化为null,前两个元素在5、6行又分别初始化,所以指向了其他的内存空间。
通过上面的分析可以看出,多维数组的本质依然是一维数组,当然一维数组的元素也可以是二维数组,这样就是三维数组,以此类推。
在Java程序中使用数组,应多从内存控制的角度来把握程序。
相关文章推荐
- 【JAVA基础教程】-浅谈数组及其内存控制
- java 基础概念 -- 数组与内存控制
- java 基础概念 -- 数组与内存控制
- Java基础复习笔记 数组,内存形式,父子,内存控制01
- JAVA--数组及其内存控制
- Java数组与内存控制(转)
- 黑马程序员-Java基础知识预备之Java流程控制与数组
- java之数组与内存控制
- (一)Java数组与内存控制
- java数组与内存控制
- 疯狂java之数组与内存控制
- JAVA基础知识学习笔记(流程控制、数组)
- 疯狂java之数组与内存控制
- 黑马程序员 JAVA初级-编程基础2 流程控制语句 函数 数组
- Java学习系列(三)Java运算符、控制语句、数组及其在内存中的运行分析
- 堆与栈的解析-以数组为例,解析数组在内存中的分布(JAVA基础-课堂笔记)
- java数组与内存的控制(1)
- 黑马程序员_java基础(2) 流程控制语句&函数与数组
- 黑马程序员_Java基础(流程控制、函数、数组)
- java基础 —— 1 子父类内存控制