String

  • Post author:
  • Post category:其他

String str = new String(“helloworld!”);

String str = “helloworld!”;//helloworld!分配到常量池中去;

在class文件中有一个非常重要的项——常量池

String,他还有两个妹妹StringBuffer,StringBuilder:

                           String(大姐,出生于JDK1.0时代)          不可变字符序列
                           StringBuffer(二姐,出生于JDK1.0时代)    线程安全的可变字符序列

                           StringBuilder(小妹,出生于JDK1.5时代)   非线程安全的可变字符序列

★StringBuffer与String的可变性问题。 
         我们先看看这两个类的部分源代码:

Java代码  
收藏代码
  1. //String   
  2. public final class String  
  3. {  
  4.         private final char value[];  
  5.   
  6.          public String(String original) {  
  7.               // 把原字符串original切分成字符数组并赋给value[];  
  8.          }  
  9. }  
  10.   
  11. //StringBuffer   
  12. public final class StringBuffer extends AbstractStringBuilder  
  13. {  
  14.          char value[]; //继承了父类AbstractStringBuilder中的value[]  
  15.          public StringBuffer(String str) {  
  16.                  super(str.length() + 16); //继承父类的构造器,并创建一个大小为str.length()+16的value[]数组  
  17.                  append(str); //将str切分成字符序列并加入到value[]中  
  18.         }  
  19. }  

      很显然,String和StringBuffer中的value[]都用于存储字符序列。但是,
      (1) String中的是常量(final)数组,只能被赋值一次。 
      比如:new String(“abc”)使得value[]={‘a’,’b’,’c’},之后这个String对象中的value[]再也不能改变了。这也正是大家常说的,String是不可变的原因 。    
      注意:这个对初学者来说有个误区,有人说String str1=new String(“abc”); str1=new String(“cba”);不是改变了字符串str1吗?那么你有必要先搞懂对象引用和对象本身的区别。这里我简单的说明一下,对象本身指的是存放在堆空间中的该对象的实例数据(非静态非常量字段)。而对象引用指的是堆中对象本身所存放的地址,一般方法区和Java栈中存储的都是对象引用,而非对象本身的数据。

      (2) StringBuffer中的value[]就是一个很普通的数组,而且可以通过append()方法将新字符串加入value[]末尾。这样也就改变了value[]的内容和大小了。

      比如:new StringBuffer(“abc”)使得value[]={‘a’,’b’,’c’,”,”…}(注意构造的长度是str.length()+16)。如果再将这个对象append(“abc”),那么这个对象中的value[]={‘a’,’b’,’c’,’a’,’b’,’c’,”….}。这也就是为什么大家说 StringBuffer是可变字符串 的涵义了。从这一点也可以看出,StringBuffer中的value[]完全可以作为字符串的缓冲区功能。其累加性能是很不错的,在后面我们会进行比较。

     总结,讨论String和StringBuffer可不可变。本质上是指对象中的value[]字符数组可不可变,而不是对象引用可不可变。 

 

 

★StringBuffer与StringBuilder的线程安全性问题 
      StringBuffer和StringBuilder可以算是双胞胎了,这两者的方法没有很大区别。但在线程安全性方面,StringBuffer允许多线程进行字符操作。这是因为在源代码中StringBuffer的很多方法都被关键字synchronized 修饰了,而StringBuilder没有。
      有多线程编程经验的程序员应该知道synchronized。这个关键字是为线程同步机制 设定的。我简要阐述一下synchronized的含义:
      每一个类对象都对应一把锁,当某个线程A调用类对象O中的synchronized方法M时,必须获得对象O的锁才能够执行M方法,否则线程A阻塞。一旦线程A开始执行M方法,将独占对象O的锁。使得其它需要调用O对象的M方法的线程阻塞。只有线程A执行完毕,释放锁后。那些阻塞线程才有机会重新调用M方法。这就是解决线程同步问题的锁机制。 
      了解了synchronized的含义以后,大家可能都会有这个感觉。多线程编程中StringBuffer比StringBuilder要安全多了 ,事实确实如此。如果有多个线程需要对同一个字符串缓冲区进行操作的时候,StringBuffer应该是不二选择。
      注意:是不是String也不安全呢?事实上不存在这个问题,String是不可变的。线程对于堆中指定的一个String对象只能读取,无法修改。试问:还有什么不安全的呢? 

 


★String和StringBuffer的效率问题(这可是个热门话题呀!) 
      首先说明一点:StringBuffer和StringBuilder可谓双胞胎,StringBuilder是1.5新引入的,其前身就是StringBuffer。StringBuilder的效率比StringBuffer稍高,如果不考虑线程安全,StringBuilder应该是首选。另外,JVM运行程序主要的时间耗费是在创建对象和回收对象上。