你好

堆栈内存

栈内存

存取速度比堆内存快

存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享。当没有引用指向数据时,这个数据就会消失。

 

堆内存

堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。

引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!

 

字符串

对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。new一次就会使用一次新地址来放东西。可以通过

System.out.println(System.identityHashCode(object)) 来查看地址

对于通过new产生一个字符串(假设为”china”)时,
会先去常量池中查找是否已经有了”china”对象,如果没有则在常量池中创建一个此字符串对象,
然后堆中再创建一个常量池中此”china”对象的拷贝对象。
这也就是有道面试题:String s = new String(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。

 java 中,直接使用==操作符,比较的是两个字符串的引用地址,并不是比较内容,比较内容请用String.equals()。

 

posted @ 2020-10-02 12:22  S_nA_tCH!  阅读(206)  评论(0)    收藏  举报