java源码解剖-字符串常量在内存中的保存方式

String类型的字符串是用char数组保存字符串的值的,

java源码解剖-字符串常量在内存中的保存方式_第1张图片

即如图的String的源码定义,它是存在char字符数组中的,所以其equals方法的是比较char数组的每一位是否相同。并且它是final类型的,不可改变。

1、显示声明的字符串是存在常量池的。

因为显示地定义字符串如"abc",它是存在常量池里的,所以如下图

java源码解剖-字符串常量在内存中的保存方式_第2张图片

对于a和a1均指向常量池中的“abc”。如下图所示:

java源码解剖-字符串常量在内存中的保存方式_第3张图片

此处引入字符串驻留,当相同的字符串常量被多次创建(使用双引号显示声明)时,字符串常量对象会被创建在常量池中,且只会创建一个对象。

2、new出来的字符串存储。

java源码解剖-字符串常量在内存中的保存方式_第4张图片

上边代码中的new字符串的过程:先将显示定义的字符串bcd存入常量池中,然后再在堆中创建一个bcd,并将s指向堆中的bcd。如下图,

java源码解剖-字符串常量在内存中的保存方式_第5张图片

3、字符串的+

        //定义1
        String c = "hello"+"world";
        
        //定义2
        String d = "he";
        String e = d+"llo";
        
        //定义3
        String f = new String("wor")+new String("ld");

 三者JVM编译后的样子:

        //定义1
        String c = "helloworld";
        
        //定义2
        String d = "he";
        String e = String.valueOf(d)+"llo";
        
        //定义3
        String f = new String("wor")+new String("ld");

定义1中c对象指向的是常量池中的“helloworld”。

定义2中String.valueOf中重新new了一个String对象,所以e指向堆内存中的“hello”。

定义3中f是在堆内存中定义了"world"。字符串的+号运算,会在堆内存中生成新的字符串对象。

写在后边的话

java7之前,保存字符串的常量的常量池在方法区(永久代)中。

java7开始,保存字符串的常量的常量池在堆中。

java7开始,intern,去常量池中寻找当前的字符串常量,如果有,那么直接返回常量池中的字符串对象,如果没有,那么会把当前的字符串常量的引用放入常量池,然后返回。

java7以前,intern,去常量池中寻找当前的字符串常量,如果有,那么直接返回常量池中的字符串对象,如果没有,那么会把当前字符串常量拷贝一个副本放入常量池中,并返回该常量。

java源码解剖-字符串常量在内存中的保存方式_第6张图片

 

 

 

 

你可能感兴趣的:(源码解剖,java7)