Java String是一个“不可变常量字符串”对象,final属性定义。之因此这么说,是从String内部在盛放字符串时候的容器char数组而言。好比当用户在初始化阶段定义了一个String对象String s=”hello,world!”,而此时再次对s进行操做改变s的值时候,如再次给s赋值使得s=”zhangphil”,那么Java的JVM实际上是再次建立了一个新的String对象,而后移动指针s指向了新的String对象(对象内部的字符串是“zhangphil”)。因而可知,假如在代码中须要频繁的修改String对象中的字符内容,那么应该尽可能避免使用String,缘由在于每一次修改String内容后,其实就是JVM在内存堆上建立了一个新的String对象,由此致使的问题有三:
(一)若是代码中的String对象频繁的修改,表面仍然是在一个String对象中修改赋值,但其实底层的JavaJVM在内存的堆上建立了更多新的String对象,同时与之相伴随的是更多死去的String对象,此过程简单总结就是Java JVM在频繁的建立对象,也产生死去的对象,即,生成一个新的String对象,死去一个String对象。这样将产生大量JVM内存碎片,极大几率提升Java了系统触发Java GC的时机,由此下降了系统性能 。
(二)String对象的产生、赋值修改操做过程是多线程不安全操做,缘由如前所述,每一次对String对象的赋值、操做,致使Java JVM在底层建立了新的String对象,在操做系统的CPU时机片上,线程不保证安全。若是多线程在操做此String对象,那么就极有可能在操做系统调度切换CPU时间片时,操做的目标对象不一致,有的指向新的String s对象,有的线程却仍指向旧的String s对象。
(三)每一次修改赋值String s对象,是建立了新的String对象,而后把新的对象引用赋给s。这个操做是在堆上建立 ,若频繁操做,势必形成较大系统开销。
小结:若是是在代码启动后,String对象再也不修改从新赋值,那么能够考虑使用String,好比在代码中定义一些public static final String常量。若是须要在代码中频繁修改和赋值操做字符串对象具体内容,建议使用StringBuffer。
不一样于String字符串常量,StringBuffer是字符串变量。StringBuffer不会产生String那样的问题:每一次修改就从新建立一个新的String对象。在某种程度上讲,StringBuffer内部维持一个可变长度的char数组盛放用户字符数据,所以StringBuffer是线程安全的。因为StringBuffer是在一个字符char数组进行原子赋值、操做,不是像String那样以“乾坤大挪移”的方式改变引用进行字符串赋值、操做,在理论上讲,字符的操做层面,StringBuffer的性能优于String。
StringBuilder是在后续新版Java中引入的字符类,StringBuilder和StringBuffer相似,均是字符串变量,可是StringBuilder多线程不安全,而单线程安全,StringBuilder在单线程中性能优于StringBuffer,所,若是仅仅是在单线程中使用字符串变量,优先可考虑使用StringBuilder。数组