存放顺序 | 存放内容 | 优点 | 缺点 | |
堆(heap) | 随意 |
类的对象,即通过new关键字 创建的对象 |
灵活性高:数据大小和生存期不必预先确定; 生存期不必预先通知编译器; 在运行时动态分配内存; 垃圾回收器自动收集不用的数据
|
存取速度较慢,因为在运行时动态分配内存 |
(堆)栈(stack) | 后进先出 |
1. 常量 2. 基本类型的变量(byte, short, int, long float, double, boolean, char) 3. 对象的引用 |
存取速度比堆快,速度仅次于直接位于CPU 中的寄存器; 可以实现数据共享 |
缺乏灵活性:存放在堆栈中的数据大小 和生存期必须是确定的。 |
注: 在Java中建立一个新的对象,会从堆和栈两个地方分配内存,在堆中分配的内存用于实际建立这个对象,而从栈中分配的内存用于存放指向堆中实际对象的引用。
疑问: String s1 = "abc" 与 String s2 = new String("abc")的区别。具体而言,对于String s1 = "abc", 先在栈中创建引用变量s1, 然后查看栈中是否有字符串常量"abc",如果有则让s1直接指向该常量的地址;如果没有,则在栈中新创建一个字符串常量"abc",然后让s1指向该常量地址。对于String s2 = new String("abc"), 这个语句,在栈中创建引用变量s2并没有什么疑问,由于使用了new关键字,肯定会在堆中新生成一个字符串对象,该字符串对象的值是"abc", 引用变量s2指向堆中新对象的地址也没有疑问。现在的疑问是究竟该字符串的值("abc")与新创建的对象一样保存在堆中,还是保存在了栈中,而堆中对象的值只是引用了栈中的地址?疑问来自于这个博客