结合JVM深入理解Java字符串


既然题目里就提到了JVM,那么首先必然要奉上两张图。

结合JVM深入理解Java字符串

image

结合JVM深入理解Java字符串

image

HotSpot JVM内存模型已经是老生常谈的知识了,所以这里也就不再赘述。直接说String。
在String类的JavaDoc开头,就有这样一句话:

Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared.

也就是说,String是不可变类。与它类似,基本类型的包装类也都是不可变类。字符串是常量,一旦初始化之后就不能更改。如果需要可变的字符串,就要借助StringBuilder和StringBuffer了。
为什么说String是不可变的?因为在它的内部是用一个final char数组来存储的。

private final char value[];

仍然举一个例子

        String s1 = "LittleMagic";
        String s2 = "LittleMagic";
        String s3 = new String("LittleMagic");
        String s4 = s3.intern();
        String s5 = "Little" + "Magic";
        String s6 = "LittleMagic2";
        String s7 = s2 + 2;
        System.out.println(s1 == s2); // true
        System.out.println(s2 == s3); // false
        System.out.println(s2 == s4); // true
        System.out.println(s2 == s5); // true
        System.out.println(s6 == s7); // false

这段代码的字节码如下。

       0: ldc           #2                  // String LittleMagic
       2: astore_1
       3: ldc           #2                  // String LittleMagic
       5: astore_2
       6: new           #3                  // class java/lang/String
       9: dup
      10: ldc           #2                  // String LittleMagic
      12: invokespecial #4                  // Method java/lang/String."":(Ljava/lang/String;)V
      15: astore_3
      16: aload_3
      17: invokevirtual #5                  // Method java/lang/String.intern:()Ljava/lang/String;
      20: astore        4
      22: ldc           #2                  // String LittleMagic
      24: astore        5
      26: ldc           #6                  // String LittleMagic2
      28: astore        6
      30: new           #7                  // class java/lang/StringBuilder
      33: dup
      34: invokespecial #8                  // Method java/lang/StringBuilder."":()V
      37: aload_2
      38: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      41: iconst_2
      42: invokevirtual #10                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      45: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      48: astore        7
      50: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;
      53: aload_1
      54: aload_2
.................

下面来逐个分析。

A pool of strings, initially empty, is maintained privately by the
class {@code String}.
When the intern method is invoked, if the pool already contains a string equal to this {@code String} object as determined by the {@link #equals(Object)} method, then the string from the pool is returned. Otherwise, this {@code String} object is added to the pool and a reference to this {@code String} object is returned.

意思就是,如果字符串常量池中已经存在一个字面量上相等(用String.equals()方法判定)的字符串,就返回常量池中的字符串。否则,就将这个字符串加入常量池,并返回它的引用。这样理解,s2与s4相等就是自然的了。

TBD

展开阅读全文

页面更新:2024-04-11

标签:字符串   兼而有之   老生常谈   常量   亦即   字面   字节   语句   也就是说   类似   对象   内存   自然   地址   方法   科技

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top