`
bcyy
  • 浏览: 1828330 次
文章分类
社区版块
存档分类
最新评论

Java进阶---数组与内存控制

 
阅读更多

Java进阶——数组与内存控制

下面将会深入探讨Java数组的静态特征。使用Java数组前必须对数组进行初始化,初始化的过程即给数组的所有元素都分配合适的内存空间,并指定初始值的过程。数组初始化以后将不能重新改变数组对象在内存中的位置和大小。从用法角度看,数组元素相当于普通变量,程序既可以吧数组的值赋给普通变量,也可以把普通变量的值赋给数组元素。但其实质是对内存中数组元素对象的操作。

1、数组初始化

Java语言是典型的静态语言,所以Java的数组也是静态的。Java中的数组必须经初始化后才可以使用,初始化即为数组对象的所有元素分配一个连续的内存空间,并为每个元素指定初始值。数组的初始化有两种方式:

>静态初始化:由程序员显式地指定每个数组元素的初始值,由系统决定数组的长度;

>动态初始化:程序员只指定数组长度,由系统为数组元素分配初始值。

下面是两种初始化方式的实例:

public class test01 {

public static void main(String[] args) {

//静态初始化数组

String[] str0 = new String[]{"小武灵灵" , "41009160"};

//静态初始化的简化形式

String[] str1 = {"小武灵灵" , "41009160"};

//动态初始化

String[] str2 = new String[2];

}

}

Java语言的数组变量是引用类型的变量,上面的三个数组变量按照声明的前后顺序(注意这里不是初始化的先后顺序)存储在main栈区中,其引用的数组是按照数组元素的顺序分别在堆内存中分配到长度为2的连续空间。

注意,虽然这里str0str1变量引用的数组内容相同,但是绝不是同一个数组,也就是说内存中除了str2外,还有两个长度内容都相同的数组。

注意,鼎泰初始化和动态初始化不能同时使用。

而执行动态初始化时,程序员指定了数组的长度,即为每个数组元素指定所需的内存空间,系统负责为这些数组元素分配初始值。系统将按照如下规则分配到初始值:

>基本类型:

>整数类型(byte , short , int , long):数组元素的初始值为0

>浮点类型(float , double)0.0

>字符类型(char , string)’\u000’

>布尔型(boolean)false

>引用类型(类、接口和数组)null

1)、数组变量和数组对象

Java的数组变量是一种引用类型的变量,通常情况下被存放在栈内存中,它并不是数组本身,它只是指向堆内存中的数组对象(C语言里的指针差不多)

数组对象是保存在堆内存中的连续内存空间。

理解了这两个概念之后,我们可以对数组的初始化有一个更深的认识,即对数组执行初始化,其实并不是对数组变量执行初始化,而是要对数组对象执行初始化(即为该数组对象分配一块连续的内存空间)

认识到这一点之后我们可以解释这样一种假象,即认为数组的长度是可变的,例如下面的实例:

public class test01 {

public static void main(String[] args) {

String[] str0 = new String[]{"小武灵灵" , "41009160" , "陕西师范大学"};

String[] str1 = new String[2];

str1 = str0;

System.out.println("str1的长度为:" + str0.length);

}

}

相信大家可以自行解释这种假象,这里我就不解释啦!

2)、基本类型数组的初始化

基本类型数组的初始化过程为:程序直接为数组分配内存空间,再将数组元素的值存入对应的内存里。例如下面的代码块:

String[] str;

str = new String[]{“小武灵灵” , 41009160, “地信1”};

注意,所有局部变量都是放在栈内存里保存的,不管其是基本类型的变量,还是引用类型的变量,都是存储在各自的方法栈区中;但引用类型变量所引用的变量(包括数组、普通Java对象)则总是存储在对内存中。

注意,引用变量本质上只是一个指针,只要程序通过引用变量访问属性,或通过引用变量来调用方法,该引用变量将会由它所引用的对象代替。

3)、引用类型数组的初始化

引用类型数组的数组元素依然是引用类型的,因此数组元素里存储的还是引用,它指向另一块内存,这块内存里存储了该引用变量所引用的对象。例如:

class Student {

public String name;

public int number;

public void output() {

System.out.println(name + “,”+number);

}

}

public class Main{

public static void main(String[] args) {

Student[] stu = new Student[2];

System.out.println(“数组长度:” + stu.length);

Student xiaowu = new Student();

xiaowu.name = “小武”;

xiaowu.number = “41009160”;

stu[0] = xiaowu;

//下面两行代码所输出的结果都是一样的

stu[0].output();

xiaowu.output();

}

}

在上面的程序中,内存是这样分配的:首先引用数组变量stu[]初始化完成后,内存中开辟出了长度为二的空间用来存储student对象;对引用变量xiaowu初始化完成后,内存中开辟了出了能够存储一个student对象长度的空间,用来存储student对象;将xiaowu赋给stu[0],则在内存中数组stu[0]指向对象xiaowu

2、数组的使用

当数组引用变量指向一个有效的数组对象之后,程序就可以通过该数组引用变量来访问数组对象。Java语言不允许直接访问对内存中的数据,因此无法直接访问堆内存中的数组对象,程序将通过数组引用变量来访问数据。

要对数组有一个更深刻的认识,需要理解两个关系:数组元素与变量间的关系、多维数组与变量间的关系。

1)、数组元素与变量间的关系

只要在已有数据类型之后增加括号,就会产生一个新的数组类型,例如:

>int à int[]:在int类型后增加[]即变为int[]数组类型

>Stirng à String[]:在String类型后增加[]即变为String[]数组类型

当程序需要多个类型相同的变量来保存程序状态时,可以考虑使用数组来保存这些变量。当一个数组初始化完成,就相当于定义了多个类型相同的变量。

无论哪种类型的数组,其数组元素其实相当于一个普通变量,把数组类型之后的括号去掉之后得到的类型就是该数组元素的类型。

从这个角度讲,数组元素就是变量。

注意,这里的数组元素并不是指数组对象中的数组元素,而是指数组变量的数组变量元素。

注意,main方法声明的变量都属于局部变量,因此它们都被保存在main方法栈中;但数组元素则作为数组对象的一部分,总是保存在堆内存中,不管它们是基本类型的数组元素,还是引用类型的数组元素。

2)、多维数组与变量间的关系

理解了数组元素与变量之间关系之后,如果已有的类型是int,在其后增加[]后得到一个数组类型;以int[]类型为已有类型,在其后增加[]后得到int[][]依然是数组类型;

int[][]类型为已有类型,在其后增加[]后得到int[][][]依然是数组类型。

从上面可以看出,所谓多维数组,其实就是数组元素依然是数组的1维数组,2维数组是数组元素是1维数组的数组,3维数组是数组元素是2维数组的数组,4维数组是数组元素是3维数组的数组……N维数组是数组元素是N-1维数组的数组。

所以,实际上我们可以这样认为:没有多维数组,只有基本数据类型和引用数据类型。

综上,数组的初始化有静态初始化和动态初始化两种;数组对象和数组变量不是同一个概念对于数组变量而言;数组元素的类型分为基本类型的数组和引用类型的数组;所有局部变量都是存放在栈内存里保存的,但引用类型变量所引用的对象则总是存储在堆内存中;一定要区分它何时只是数组变量,何时代表数组对象本身;数组元素就是变量,没有多维数组。

分享到:
评论

相关推荐

    JavaSE进阶数组讲义

    数组是一种引用数据类型,在内存中存储示意图如下: 1. 数组是一组数据的集合 2. 数组作为一种引用类型 3. 数组元素的类型可以是基本类型,也可以是引用类型,但同一个数组只能是同一种类型 4. 数组作为对象,...

    编程新手真言......

    第三部分 进阶: C,C++代码阅读与控制 201 第9章 语法与初级标准库 202 9.1 C++的基于过程设计 203 9.2 C++的基于对象设计: 模板与设计 203 9.3 面向对象设计 204 9.4 泛型开发与初级StdC库 204 第10章 数据逻辑与...

    java内核源码-JavaCompass:「Java指南针」为你学习Java指明方向。内容涵盖互联网Java工程师所需要掌握的核心知识,涉及J

    数组&链表进阶 栈 队列 算法思想 数论&枚举&递归&分治&回溯 排序及其源码实现 贪心&动态规划 高级数据结构 树论基础&二叉树 二叉搜索树&红黑树 BTree Trie树&赫夫曼树 堆树 图论基础 最短路径 高效查找算法 二分&...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    本书是第II卷,以开发人员在项目开发中经常遇到的问题和必须掌握的技术为中心,介绍了应用Java进行桌面程序开发各个方面的知识和技巧,主要包括Java语法与面向对象技术、Java高级应用、窗体与控件应用、文件操作...

    java学习笔记–java基础

    java基础1.1 输入输出用户交互Scanner用户交互Scanner进阶1.2 基本数据类型基本数据类型类型转换变量,常量,作用域运算符补充:包机制补充:JavaDoc1.3 顺序结构1.4 循环结构while循环do-while循环for循环增强型for...

    代码之美(中文完整版).pdf

    2.1 版本控制与目录树的转换 2.2 表达目录树的差异 2.3 增量编辑器接口 2.4 但这是不是艺术? 2.5 像体育比赛一样的抽象 2.6 结论 第3章 我编写过的最漂亮代码 3.1 我编写过的最漂亮代码 3.2事倍功半 3.3 观点 3.4 ...

    40亿个非负整数中找到未出现的数

    进阶: 内存限制10MB,但是只用找到一个没出现过的数即可。 常规方法:假设用哈希表来保存出现过的数,那么如果40亿个数都不同,则哈希表的记录数为40亿条,存一个32位整数需要4B,所以最差情况下需要40亿×4B = 160...

    快速入门Go语言(转行Go开发必修课程)

    Go被称为“21世纪的C语言”,因其简洁的语法,以及自带的内存回收机制,使其可以拥有高速运行效率的同时,还能兼顾开发效率,所以越来越多大厂开始转投Go语言! 转行学习误区多  学习效率Down到底 在实际的开发...

Global site tag (gtag.js) - Google Analytics