java的堆栈机制与String对象

首先理解几个概念:

栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)

当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

堆:存放所有new出来的对象。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。

常量池:在堆中分配出来的一块存储区域,存放字符串常量和基本类型常量(public static final)

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

 

 

大家先来看看下面这段程序:
public class Test{
    public static void main(String args[])
{
    String str1 = "abc";
    String str2 = "abc;
    String str3 = new String("abc");

    System.out.println(str1 == str3);
    System.out.println(str1.equals(str3));
    System.out.println(str2 == str1);
}
}
这段代码的运行结果是:
println输出的是false;而第二句则输出为true;但是第三句却是true。

str1,str2是栈内变量,它的内存保存的是常量池的常量字符串对象对象"abc"的地址
str3是栈内变量,它的内存保存的是堆中的new String对象的地址,new String在堆中生成对象,并用常量池的字符串对象"abc"初始化堆中的对象,所以堆中的对象的内存的内容和常量池对象的内存的内容一样,但是是不同的两个对象



在这里很多人会误认为第一句应该是true的,但是事实却是false。这是因为第一句在进行“==”比较的时候比较的是两个指向,而不是具体指向的内容。而第三句在进行“==”比较的时候同样比较的是指向,但是他们的指向是相同的。这种现象出现的原因和字符串在内存中实例化的时候有关。
具体情况如下图所示:



当执行第一句Str1 = "abc" 实例化出第一个指向;当进行第二句Str2 = "abc" 的时候出现第二个指向,因为堆内存中存在"abc",而且str2也没有new一个新的对象,所以为了节省内存,str2指向了str1所指向的对象;但是第三句的时候出现new语句,他实例化出了一块新的空间用来盛放"abc",自然str3的指向也也是指向这段新开辟的空间。

你可能感兴趣的:(string,java,存储,equals,虚拟机,class)