对string、stringbuilder、stringbuffer全面解析

来源:互联网 发布:adams软件简介 编辑:程序博客网 时间:2024/06/05 18:43

我想大家对string这个名称不会陌生吧!那对string内部了解多少呢?

废话不多说了,analyzing。。。。

one: String类是不可变的,String的实例一旦生成就不会再改变了

eg:

Java代码
  1. String str="a"+"b"+"c"+"a";  
String str="a"+"b"+"c"+"a";

 

question:上面程序中可以看到在我们的constant pool(常量池)存在那些的字符串常量呢?

answer: six     是不是有点不好理解呢?

由于string类是不可变的,所以上面的程序除了3个直接量外(为什么会是3个直接量呢?因为第一个“a”和最后那个“a”在constant pool中其实是同一个,下面会进行详细分析的),还有额外的生成3个分别由"a"+"b"生成"ab" 保存在内存中,接着"ab"+"c"生成"abc"保存在内存中,最后由"abc"+"a"生成"abca"保存在内存中

所以在我们的constant pool 里面就存在了"a"、"b"、"c"、"ab"、"abc"、"abca"个字符常量

 

two :对于上面这样也产生了一个问题,正因为string类是不可变的,同时也产生很多额外的临时变量,所以才引发了stringbuffer和stringbuilder这两个类来避免这个问题

question 01:stringbuffer和stringbuilder两个有什么差别呢?

answer :其实他们的用法都差不多只是他们一个线程安全和一个是线程不安全的

 

stringbuffer:是线程安全的

stringbuilder:是线程不安全的,虽然是线程不安全,但是在性能方面就比较好了

 

 

question 02: 很多人问我String str1="hello"和 String str2=new String("hello");有什么区别呢?

answer: 为了解释这个问题,首先你要对constant pool了解。

              question :什么是constant pool(常量池)呢?

              answer:常量池指的是在编译期被确定的,并被保存在已编译的.class文件中的一些数据,它包括了关于类

                            、方法、接口中的常量,也包括字符串常量

eg:

Java代码
  1.  String s0="hello" ;   
  2.    String s1="hello" ;   
  3.    String s2="hel" + "lo";    
  4.    System.out.println(s0==s1);    
  5.    System.out.println( s0==s2 );  
 String s0="hello" ;   String s1="hello" ;   String s2="hel" + "lo";    System.out.println(s0==s1);    System.out.println( s0==s2 );

 

rusult:

Java代码
  1. true  
  2. true  
truetrue

 

结果都为true,说明了一点都来自一个常量池中字符串常量

如果还不理解的话可以看下面这个程序

eg:

Java代码
  1. String s0="hello" ;   
  2. String s1="hello" ;   
  3. String s2="hel" + "lo";    
  4. System.out.println(System.identityHashCode(s0));    
  5. System.out.println(System.identityHashCode(s1));   
  6. System.out.println(System.identityHashCode(s2));  
String s0="hello" ;String s1="hello" ;String s2="hel" + "lo"; System.out.println(System.identityHashCode(s0)); System.out.println(System.identityHashCode(s1));System.out.println(System.identityHashCode(s2));

 result:

Java代码
  1. 26399554  
  2. 26399554  
  3. 26399554  
263995542639955426399554

 

identityHashCode(Object o)是System类里的一个一个方法,该方法返回指定对象的精确hashCode值,也就是根据该对象的地址计算得到的hashCode值。如果两个对象indentityHashCode值相同,则两个对象绝对是同一个对象

由上面的程序可以看出s0 s1 s2指的是同一个对象

 

 

还有一个判断方法

eg:

 

Java代码
  1. String s0="hello" ;   
  2. String s1="hello" ;   
  3. String s2="hel" + "lo";    
  4. System.out.println(s0==s0.intern());    
  5. System.out.println(s1==s0.intern());   
  6. System.out.println(s2==s1.intern());  
String s0="hello" ;String s1="hello" ;String s2="hel" + "lo"; System.out.println(s0==s0.intern()); System.out.println(s1==s0.intern());System.out.println(s2==s1.intern());

 

result:

Java代码
  1. true  
  2. true  
  3. true  
truetruetrue

 

存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;

 

对new String("hello");的理解

String(String s):初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。

 用new String();来创建的字符串不是常量,因为在编译期这个常量并不能确定,所以new String()创建的字符串不会放入常量池中,他们有自己的地址空间

 

stringbuffer   stringbuilder提供了系列插入、追加、改变该字符串里包含的字符串系列