美文网首页
String内存分析

String内存分析

作者: 一如既往wfqwfq | 来源:发表于2019-08-26 22:38 被阅读0次

    1、了解常量池

    字符串常量池中存储的就是各种字符串,在常量池中这些字符串都是唯一的。字符串常量池中存储的是在编译期就确定的,存在.class文件中的字符串常量。字符串常量池能有效地减少内存开销,毕竟程序中出现相同的字符串是很大概率的事情,如果为每个字符串都去开辟内存空间,后果可想而知。

    2、内存分析

    1、创建String的基本方式

    String s1 = "abc";  
    String s2 = new String("abc"); 
    
    • String s1 = "abc" 创建过程:先去常量池中查找是否有"abc"这个字符串,如果有,则直接返回引用给s1,没有的话在在常量池中创建"abc",并返回引用给s1。"abc"是一个字符串,直接把字符串赋给一个变量,这在编译期就可以确定。
    • String s2 = new String("abc")创建过程:先在堆中创建一个"abc"对象(当然个人认为这不是在将"abc"直接存在堆中),在常量池中查找是否有"abc"。如果有,则让堆中的"abc"对象直接指向常量池中的"abc"。如果没有,则在常量池中创建"abc",并使堆中的"abc"对象直接指向常量池中的"abc"。


      image.png

      这个图之前在网上也是有看过的,不过关于new String(),网上有许多的说法,这个图也是经过实验得出来的,下面上实验过程。

    class Person{
        String name;
        public Person(String name){
            this.name = name;
        }
    }
    public class StringHeapTest {
        public static void main(String[] args) {
            String s1 = "abc";
            String s2 = new String("abc");
            System.out.println(s1 ==  s2);  //false,s1指向常量池,s2指向堆中,所以地址不同
    
            Person p1 = new Person("xiaoming");
            Person p2 = new Person("xiaoming");
            System.out.println(p1.name == p2.name);  //true,堆中地址都指向常量池中的"xiaoming"
        }
    }
    

    结论:通过String a = "a";方式创建的String对象,一般情况下栈中变量直接指向常量池(String.intern()方法可能会影响结果)。
    String a = new String方式创建的String对象,栈中变量指向堆中,堆中对象中存储这该字符串在常量池中地址,由堆中在指向常量池。所以我们看到的直接字符串赋值和new String()出来的地址是不同的,堆中两个Person对象的name属性,它们的地址是相同的,都是指向常量池中"xiaoming"。

    2、String拼接

    String s1 = "a" ;
    String s2 = "abc"
    String s3 = s1 + "bc";
    

    相关文章

      网友评论

          本文标题:String内存分析

          本文链接:https://www.haomeiwen.com/subject/gyhjectx.html