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 = "张三"  \neq String a = new String("张三"),其本质上是虚拟机的规则。

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

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

对象创建过程
局部变量创建流程

 

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

 

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值