String类

1.String、StringBuilder、StringBuffer 

  描述  
String

不可变性 

string 是一个不可变类,每次 new 都会创建一个新的对象,存储在字符串常量池
StringBuilder 可变性 线程不安全   扩容   int newCapacity = (value.length << 1) + 2; 
StringBuffer  可变性 线程安全  底层使用的 synchronized 实现线程安全     扩容   int newCapacity = (value.length << 1) + 2; 

String  jdk 9 之前 底层是用 char value[],jdk 9 之后采用的是 byte value [] (减小空间的浪费); 

 

 2. 对象创建过程

由于字符串类比较特殊, 从JVM 的角度理解 String a = "张三"   String a = new String("张三"),其本质上是虚拟机的规则。

局部变量存储在方法栈局部表量表中,最终指向的是同一个引用地址,存储在字符串常量池中的地址

字符串常量池 : 不会存储相同内容的字符串    (底层实现HashTable ,默认长度60013,长度越小则,hash冲突越大会降低查询时间,降低效率)

<figcaption> 局部变量创建流程 </figcaption>

 

3 string 操作

string a = “a”;     string b = “a”;   string a1 = new string("a");

代码 注释
string a1 = new string("a"); 堆空间中创建一个对象
string c = "a"+"b"; 常量常量的拼接直接在常量池中进行(编译器就已经完成)    final 修饰的变量,虽然也是引用,但也是视为常量
string c1 = a + a1; 变量参与的拼接是在中进行 (等价于在堆空间中新创建了一个对象) string c1 = new StringBuilder().append(a).append(a1).tostring();
string.intern() 若常量池中存在则返回地址,否在常量池中创建一个并返回地址

从指令源码理解对象常见过程

 

String a = "ab";

string a = new string("ab");

string a = new string("a") + new string("b")

String a = new String("a") + new String("b");
a.intern();     String b = "ab";

字节码指令

0 ldc #2 <ab>
2 astore_1
3 return

 0 new #3 <java/lang/String>
 3 dup
 4 ldc #2 <ab>
 6 invokespecial #4 <java/lang/String.<init>>
 9 astore_1
10 return
 

 0 new #5 <java/lang/StringBuilder>
 3 dup
 4 invokespecial #6 <java/lang/StringBuilder.<init>>
 7 new #3 <java/lang/String>
10 dup
11 ldc #7 <a>
13 invokespecial #4 <java/lang/String.<init>>
16 invokevirtual #8 <java/lang/StringBuilder.append>
19 new #3 <java/lang/String>
22 dup
23 ldc #9 <b>
25 invokespecial #4 <java/lang/String.<init>>
28 invokevirtual #8 <java/lang/StringBuilder.append>
31 invokevirtual #10 <java/lang/StringBuilder.toString>
34 astore_1
35 return

 0 new #5 <java/lang/StringBuilder>
 3 dup
 4 invokespecial #6 <java/lang/StringBuilder.<init>>
 7 new #3 <java/lang/String>
10 dup
11 ldc #7 <a>
13 invokespecial #4 <java/lang/String.<init>>
16 invokevirtual #8 <java/lang/StringBuilder.append>
19 new #3 <java/lang/String>
22 dup
23 ldc #9 <b>
25 invokespecial #4 <java/lang/String.<init>>
28 invokevirtual #8 <java/lang/StringBuilder.append>
31 invokevirtual #10 <java/lang/StringBuilder.toString>
34 astore_1
35 aload_1
36 invokevirtual #11 <java/lang/String.intern>
39 pop
40 ldc #2 <ab>
42 astore_2
43 return
解释 0 ldc #2 <ab> 直接从字符串常量池中获取 "ab"

 0 new #3 <java/lang/String>  首先创建对象

4 ldc #2 <ab> 直接从字符串常量池中获取 "ab"

 0 new #5 <java/lang/StringBuilder>  先创建的StringBuilder对象

11~28 依次创建 a 、b,中间采用append方法

31 invokevirtual #10 <java/lang/StringBuilder.toString>  

  a == b             true

重点

  • invokevirtual #10 <java/lang/StringBuilder.toString>   这个步骤会先判断 new String ("ab"), 但是不会在字符串常量池中创建 “ab” .
  • 只有手动调用 intern() 常量池才能在常量池创建,并返回该字符串的地址 (jdk6  | jdk7 字符串常量池存放的是堆空间字符串的地址,而不是创建字符串

扩展

String a = new string("a") + new string("b");
String b = "ab";
String c = a.intern();


# a==b   false 
# b==c   true

 

全部评论

相关推荐

03-14 11:58
门头沟学院 Java
腾讯暑期实习java选手,完全不懂C++,貌似游戏行业都是用C++的而且天美好像在成都,个人比较想去上海或深圳
siestaaaaaa:天美不止在成都,深圳上海都有。 游戏服务器也不全是cpp,至少我们项目是java ,但是工作中什么语言都会用到,比如cpp、lua、py等等,语言本身其实不重要
点赞 评论 收藏
分享
03-14 18:48
重庆大学 C++
点赞 评论 收藏
分享
纸鹰:对他说:“你好,我是百度JAVA。”
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务