其实引用这种机制就像C语言中的指针,在一块内存中存放一个指针类型的变量,另一块内存存放一个与指针数据类型相同的变量,然后指针变量指向该变量的地址。
Java内存分配
Java在创建一个对象时,会分配两块内存,一块内存位于栈内,而另一块内存位于堆内。位于栈内的那块内存的内容记录了堆的位置信息,也即栈那块内容指向对应的堆里面的那块内存。
为什么new对象的内存是位于堆内?
我们知道,Stack放置局部变量,堆放置动态分配的内存。由于new出来的对象是实例,在编译的时候并不知道它需要多大的内存,只有在执行的时候才知道对象实例的内存大小,这种就是动态分配。一方面是因为堆是放置动态分配的内存的,动态分配的对象实例固然是放置在其中,另一方面,也只有堆才有足够的内存进行动态分配内存
Java内存分配中的栈
在函数中定义的一些基本类型的变量数据和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当该变量退出该作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
Java内存分配中的堆
堆内存用来存放由new创建的对象和数组。 在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。
在堆中产生了一个数组或对象后,还可以 在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。引用变量就相当于是为数组或者对象起的一个名称。
引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍 然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。
对象与对象引用
接下创建一个类来具体讲解:
public class Test {
//类的构造方法
}
//创建一个Test类对象
Test test = new Test();
在上面的例子中
Test test = new Test();
这一语句,包括了四个作用:
(1)右边的“new Test”,是以Test类作为模板,在“堆空间”里创建一个Test对象。
(2)末尾的()意味着,在对象创建后,立即调用Test类的构造函数,对刚生成的对象test进行初始化。
(3)左边的“Test test”创建了一个Test类引用变量,它存放在“栈空间”中。也就是用来指向Test对象的“对象引用”。
(4)“=”操作符使“对象引用”指向刚创建的那个Test对象。
![V)_8UQ}1K09IAVRURHA7E4.png