一. 前言
因为没有研究过Java虚拟机,所以关于Java的基本类型和引用类型的内存分配等知识一直是自己比较迷糊的一个点,特将相关知识整理如下,为以后学习虚拟机打好基础,因为刚接触内存这一块的知识,难免有理解不当的地方,还请大家多批评指教。最新更新时间(版本:1.2 /2019 / 3.6 )
二. 栈和堆
Java开辟了两类存储区域,分别是堆和栈。想要弄明白Java的内存分配,首先得搞明白栈和堆的区别,这里引用Sarah_mq《Java对象和引用变量》一文的解释:
存储区域 | 存储内容 | 优点 | 缺点 | 回收 |
栈 | 基本类型的变量和对象的引用变量 | 存取速度比堆要快,仅次于寄存器,栈数据可以共享 | 存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量 | 当超过变量的作用域后,Java会自动释放掉该变量,内存空间可以立即被另作他用 |
堆 | 由new等指令创建的对象和数组 | 可以动态地分配内存大小,生存期也不必事先告诉编译器 | 由于要在运行时动态分配内存,存取速度较慢 | 由Java虚拟机的自动垃圾回收器来回收不再使用的数据 |
三. 基本类型
关于基本类型的变量大多数人存在一个误解,认为基本类型的变量都是存在于栈中的,其实基本类型的变量还有可能存在堆中:
存放在堆中的基本类型变量
public class Test { int i = 3; }
另外基本类型的数组也是存放在堆中,后面会详细解释,这里暂不赘述。
四. 引用类型
引用类型有多种,这里我们以类为例讲解。假如有一个Dog类,该类有name,age,variety 三个属性。首先给出实例化对象的步骤:
每个步骤的操作如下:
1. 声明一个引用变量
2. 创建Dog对象
3. 链接对象和引用变量
4. 为Dog对象的属性赋值
五. 基本类型数组
在数组中,无论是基本类型还是引用类型,栈中保存的都只是一个引用变量,不保存实际的值。
以下面的数组为例:
int[] nums = new int[3];
1:声明一个int类型的名为nums的数组变量
2:创建大小为3的数组
3.: 将上面创建的数组赋值给之前声明的nums变量
4: 为数组的每个元素赋值
可以看到,基本数据类型在堆中的每个元素保存都是int类型的值,但是数组本身却是个对象,要存在栈中。
六. 引用类型数组
还是以Dog类为例:
Dog[] dogs= new Dog[3];
1: 声明一个Dog数组引用变量
2 : 创建一个大小为3的Dog数组
3 :将创建好的数组赋值给dogs
注意此时的dogs这个数组中的每个元素保存并不是Dog对象本身,而是引用,也就是说此时虽然有了Dog的引用,但却没有实际的Dog对象。
4 :创建Dog对象并赋值给dogs数组的元素
可以看到,基本类型和引用类型的数组元素都保存在堆中,但是两者在堆中保存的内容却是有区别的,以int和Dog为例:
int类型的数组的每个元素存放的都是一个int类型数据
但是Dog类型的数组每个元素存放的却不是一个Dog对象,而是一个引用。
六. 引用传递
还是以Dog类为例,创建一个Dog类,并实例化一个myDog变量并赋值:
再实例化一个yourDog变量并赋值
把变量myDog赋值给yourDog,则变量yourDog就会被抛弃,等待垃圾回收器回收
此时myDog和yourDog对象的属性值相等,修改任何一个变量的属性值,另一个变量也会被影响。
数组无论里面的元素是基本类型还是引用类型,数组本身都是一个引用类型,所以数组同样适用于引用传递的性质。
请登录之后再进行评论