Java中的基本类型和引用类型

来源:互联网 发布:cutecom串口发送数据 编辑:程序博客网 时间:2024/05/19 18:46

上课的时候老师问到了这个问题,Java中基本类型和引用类型的区别,不假思索的回答:基本类型就是直接分配空间的变量,引用类型就是指向内存空间的一个引用。当时觉得自己还是理解一些的,可过后自己去思考,觉得对这个问题的理解不够深入,到底是在哪里分配空间呢?引用类型的存储地址的变量分配在哪里呢?带着这些困惑我开始了查找资料和理解的道路,自己做一些笔记。
一、基本类型
基本类型变量存储的是一个确定类型的值,java有8大基本类型,分别是boolean、char、byte、short、int、long、float、double。基本类型在创建的时候,基本类型的内存大小是已知的,系统会为你在栈(Stack)上分配相应的内存空间,存储相应变量的值。例如:

int x = 666;

其实我们都知道这是两个步骤,也可以写成

int x;    //声明变量、分配空间(在栈上)x = 666;  //赋值

首先是声明了变量x,向系统在栈上申请了相应的空间;之后在把666赋值给了变量x,即写入了相应的内存空间。
栈内存空间是可以快速被别人使用的,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

二、引用类型
引用类型顾名思义,“引用”了一个对象,那它自己呢?它存储的是指向相应空间的“引用”,也就是对象真正存储内存的地址。引用类型创建的存储地址的变量和基本类型一样,在栈(Stack)上进行分配内存,而对象真正存储的位置是在堆(Heap)上分配的空间,也称之为堆内存。例如:

MyClass a = new MyClass(666);

同样的我们可以写为

MyClass a;             //在栈上分配内存给引用类型变量aa = new MyClass(666);  //做2、3步骤

这其中主要包含三个步骤:
1、创建引用类型的变量a,在栈内存上为其分配内存(所占用的内存大小是固定的,即存储地址所需要的大小)
2、在堆内存上为创建的MyClass对象分配内存大小(这个大小是系统事先不知道的,取决于MyClass类的实现),调用构造函数初始化字段。
3、将MyClass在堆中的地址赋值给栈中的a变量
我们从这三个步骤可以看出引用的真正含义,就是存储变量所在的堆内存中的地址,而这个变量真正是存储在堆内存中的,我们不难看出,引用类型的分配过程远远比基本类型复杂的多。

三、栈内存和堆内存的区别
上面我们知道了基本类型和引用类型的区别,那么栈和堆究竟为什么要这么分配呢?我引用一下网上的一段话:
“Java 的堆是一个运行时数据区,类的(对象从中分配空间。它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(int, short, long, byte, float, double, boolean, char)和对象句柄。 ”
也就是说,栈内存比堆内存高效,但高效牺牲了灵活性,而堆是一种灵活的内存,动态分配大小。我们也可以知道GC负责的是堆的回收,而栈是自动释放内存的。

讲了这么多,我们总结一下:
基本类型直接分配在栈内存中,会自动释放;而引用类型的真正对象分配在堆内存中,用GC负责管理,引用类型变量只是在栈中分配的固定区域存储了真正对象的地址而已,通过句柄可以找到真正对象的详细信息。

1 0
原创粉丝点击