优秀的编程知识分享平台

网站首页 > 技术文章 正文

String性能问题之字符串复用(string的复制)

nanyue 2024-08-27 18:11:24 技术文章 6 ℃

在深入学习String的性能问题前,我们先来看一道常见的面试题,代码如下:

        String str1 = "abc";
        String str2 = new String("abc");
        System.out.println(str1 == str2);

我们创建了两个对象来比较他们是否相同,你可以先思考下答案以及其中的原理,通过下面的阅读,一定能让你完全掌握相关的知识。(本文基于java8讲解)

首先我们知道,String类创建出的字符串对象是不可变对象,在java8的源代码中,String类中定义了一个char数组变量value和int变量hash来存储当前String对象的字符串值以及该值的hash码,数组采用final修饰,因此一旦创建即不可修改,但为什么要使用final修饰,或者说为什么一定要不可变,我们在后续文章再详细解读。具体代码定义如下:

    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

接下来,我们还需要明确一点,jvm为了让字符串常量能够复用,专门在堆上分配了一部分空间,用来存储字符串常量,称为字符串常量池(String pool),那什么场景下定义的字符串会被放入常量池呢,我们一起来看下下面这张原理图:


显然不论是String str="abc" 或者String str=new String("abc")代码,在类初次加载时,字符串常量"abc"都会被加入到字符串常量池,前者在运行时,会直接返回常量池中的字符串引用,而后者则会让在堆上创建出的String对象引用常量池中的字符串对象”abc“,返回String对象的引用。我们实际执行下代码,查看结果,同时使用debug方式查看下对象引用的字符串对象数组的引用,看下是否和我们理解的一致:


通过结果,相信大家也已经知道了题目的答案,我们简单总结下:

1.new String("abc")的写法返回的是创建的String对象的引用,因此和常量池中的字符串"abc"的索引不相等。问题的结果为false。

2.在创建String时,推荐大家使用String str="abc"的写法,这样写的好处也很明显,可以在堆上少创建一个String对象,节省内存空间的使用,其实在如果你使用了new String("abc")的写法,IDE也会提示你舍弃这种写法。

3.字符串常量池的出现给了我们复用字符串以节省内存空间的思路,那除了字面量字符串在类加载时会将字符串加入常量池以便后续复用外,还有什么办法能将字符串加入常量池呢?以及这里的字面量字符串具体是怎么理解呢?

因篇幅限制,我们在下一章节对遗留的问题再做详细的讲解和描述,感兴趣的小伙伴可以关注作者,一起学习交流,谢谢大家!

最近发表
标签列表