StringPool 与面试

本贴最后更新于 3004 天前,其中的信息可能已经水流花落

1.问题起源

    public static void main(String[] args) {
    String s1 = "abc";
    String s2 = "ab";
    String s3 = "c";
    String s4 = s2 + s3;
    String st0 = "helloworld";
    String st1 = "helloworld";
    String st2 = "hello" + "world";
    System.out.println(st0 == st2);
    System.out.println(s1 == (s2 + s3));
    System.out.println(s1 == s4);

}

答案全是false,为什么呢?

2.String pool

就像名字说的一样,String pool就是String对象池,或者说是集合。在java堆中特地开辟出来的空间存储String对象。java引入String pool这一个结构来优化String对象的定位和存储。

String类型是Java最常用的类型,而且非常消耗内存。与其建立多份的String对象不如共享相同的实例对象。

3.举栗子

3.1

  public static void main(String[] args) {
    String s1 = "Cat";
    String s2 = "Cat";
   String  s3 = new String("Cat");     

    System.out.println(s1 == s2); //true
    System.out.println(s1 == "s3); //false
}</pre>

看图说话

众所周知,String对象是不可变的,值相同的String对象指向相同的实例。图中的Stringpool中值为“Cat”的String对象仅仅建立和存一次。当你再次使用String s2=“Cat”时 s2立刻指向了String pool中的“Cat”实例。这个只会在你使用硬编码,就是用字符串拼凑,一个一个字母输入的时候才会发生。s3使用了new建立了一个全新的String对象(“Cat”)它没有保存在String pool,而是保存在正常的堆中。

3.2

 

public static void main(String[] args) {
    String s1 = "Cat";
    String s2 = "Ca";
    s2 = s2 + "t";

    System.out.println(s1 == s2); //false

}</pre>

 String是不可变的,当使用“+”连接两个String对象时底层调用的是StringBuilder,利用StringBuilder进行字符串的拼接。这样会返回有个全新的String实例,并保存在堆中,并不会放入String Pool中。不想要创建新的String对象,想利用String pool中的实例,可以利用String.intern()方法,返回String pool里面的一个已有的String对象

 

String s1 = "abc";
String s2= "abc";

String s3 = new String("abc");

System.out.println(s1 == s2);
System.out.println(s1 == s3);

s3 = s3.intern();
System.out.println(s1==s3);


 

 

 

4.证明

public static void main(String[ ] arg){
    String s1 = "abc";
    String s2 = "ab";
    String s3 = "c";
    String s4 = s2 + s3;
    String st0 = "helloworld";
    String st1 = "helloworld";
    String st2 = "hello" + "world";
    System.out.println(st0 == st2);
    System.out.println(s1 == (s2 + s3));
    System.out.println(s1 == s4);
}</pre>

回到一开始的代码块,利用javap命令查看编译后的二进制class文件,截图如下:

从常量池中可以看出类型为String的常量只有#2("abc'),#3("ab"),#4("c"),#9("helloworld"),而且有StringBuilder类的相关方法的调用,验证了String "+"操作利用了StringBuilder.append()方法。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖
  • 字符串
    30 引用 • 57 回帖
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    325 引用 • 1395 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • zonghua

    这种问题看了一次又一次,但是还是有可能答错

  • 其他回帖
  • Eddie

    (눈_눈」∠)

  • yangyujiao

    貌似有个公司问过我。String 是定长的,那 S1+S2 那样的是怎么回事···。内存如何变化的····

    1 回复