从Java字符串常量池谈起

目录

0、写在前面

本节主要分析String Constant Pool(SCP),即字符串常量池;该内容原属于软件构造系列文章Chapter8,由于比较重要,在此特别分析。

1、字符串常量池介绍

字符串常量池Heap中包含字符串对象引用特殊内存区域。

2、创建字符串的两种方式

创建一个字符串有两种方式
(1)使用字面量(保存在字符串常量池中,所有相同内容的字符串引用相同)

String s = "java";

每当我们创建字面量时,JVM都会检查字符串常量池。如果该字符串已存在于池中,则会提取其引用。 -如果该字符串不在池中,则会在其中创建一个新的字符串对象。

(2)使用关键字new(保存在heap,即使内容相同,引用也不同)

String s = new String("java");

当我们使用new关键字创建字符串时,它会保存到堆中
举个例子
这里写图片描述
其中s1==s2结果为true,引用相同;s1==s3结果为false,引用不同;当然s1.equals(s2)s1.equals(s3)均为true,因为字符串本身相同。

esp. intern()
可以将new创建的String对象转为字面量。

    String a = new String("a");
    String b = a;
    String c = "a";
    /* false, 此时b是堆中的a的引用, c在字符串常量池 */
    System.out.println(b == c);

    b = a.intern();
    /* true, b引用字符串常量池中的c */
    System.out.println(b == c);

    /* false, a.intern()操作没有改变a对象 */
    System.out.println(a == c);

调用方法a.intern()的时候会返回"a",但是这个方法会首先检查字符串常量池池中是否有"a"这个字符串,如果存在则返回这个字符串的引用,否则就将这个字符串添加到字符串池中,然会返回这个字符串的引用。

3、String & StringBuilder & StringBuffer

考虑如下代码

    String s = "";
    for(int i = 0; i < 1000; i++){
        s = s + "a";
    }

s = s + "a"会在字符串常量池中创建"a", "aa", "aaa", …,产生大量的临时对象,十分耗费空间。
引入StringBuilder

    StringBuilder s = new StringBuilder();
    for(int i = 0; i < 1000; i++){
        s.append("a");
    }

总共只创建了一个String对象。
引入StringBuffer
StringBufferStringBuilder几乎没有差别,主要在于StringBuffer成员方法前多了关键字synchronized,因此是线程安全的。

4、Q & A

由于字符串常量池存在,可以很大程度上节省空间,因此会有一些特殊情况。

Q:String s = "a" + "b"创建了几个String对象?
A:一个。”a”, “b” 都是常量,在编译的时候直接优化为一个常量”ab”。

Q:String s = new String("a")创建了几个String对象?
A:两个,首先创建一个字面量”a”,然后将字面量”s”作为参数,创建一个字符串对象s。(其实在栈上还有一个指向s的引用,不过,不是字符串对象)

Q:

String s = new String("a" + "b");

Line 3会创建几个String对象?
A:两个,编译器优化直接创建字面量”ab”,之后创建s对象。

Q:

String a = "s" + new String();
String b = "s" + new String();
System.out.println(a == b)

A:打印结果为false,此时a和b为两个字符串对象。

参考:
Java intern() 方法
探秘Java中的String、StringBuilder以及StringBuffer
String s=”a”+”b”+”c” 创建了几个对象(评论很有意思)
String s=new String(“abc”) 创建了几个对象?
Java细节:字符串的拼接
Java中的字符串常量池

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值