String
String对象是一组不可改变的unicode字符序列,是字符串常量;它们的值在创建之后不能改变。
1、String对象的初始化
String s1 = “Test”;
String s2 = “Test”;
其创建的时候回到方法区的常数据区查询是否有“Test”,如果有,就直接引用即可,如果没有,则会到常数据区去创建一个字符串“Test”字符串,这个“Test”字符串是可以共享的。再将该字符串的引用在栈中创建。
String s3 = new String(“Test”);
先到方法区的常数据区查询有没有“Test”这个字符串,查询到了就直接引用,然后在堆中创建了一个String对象,这个对象的空间中保存了“Test”字符串的地址。也就是说指向了常数据区中“Test”地址,最后在桟中创建了一个String类型的引用变量s3,指向了堆中的String对象。
这种方式,实际上创建了两个String对象,一个是”Test”对象,存储在常量空间中,一个是使用new关键字为对象s3申请的空间。
2、 创建了几个对象?
String str="abc";
毫无疑问,这行代码创建了一个String对象。
String a="abc"; String b="abc";
那这里呢?答案还是一个。
String a="ab"+"cd";
再看看这里呢?答案是三个。
3、String类对象为不可变对象,一旦你修改了String对象的值,隐性重新创建了一个新的对象,释放原String对象。
StringBuffer
StringBuffer: 线程安全的可变字符序列,是字符串变量,它的对象是可以扩充和修改的。
StringBuffer类和String一样,也用来代表字符串,但是StringBuffer的内部实现方式和String不同,StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。
在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuffer要更加适合一些。
1、StringBuffer对象的初始化
例如:
StringBuffer s = new StringBuffer();
这样初始化出的StringBuffer对象是一个空的对象。
如果需要创建带有内容的StringBuffer对象,则可以使用:
StringBuffer s = new StringBuffer(“abc”);
这样初始化出的StringBuffer对象的内容就是字符串”abc”。
需要注意的是,StringBuffer和String属于不同的类型,也不能直接进行强制类型转换,下面的代码都是错误的:
StringBuffer s = “abc”; //赋值类型不匹配
StringBuffer s = (StringBuffer)”abc”; //不存在继承关系,无法进行强转
StringBuffer对象和String对象之间的互转的代码如下:
String s = “abc”;
StringBuffer sb1 = new StringBuffer(“123”);
StringBuffer sb2 = new StringBuffer(s); //String转换为StringBuffer
String s1 = sb1.toString(); //StringBuffer转换为String
API文档的一些介绍:
1、Java.lang.StringBuffer 线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。
2、StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。
StringBuilder
线程不安全的可变字符序列,字符串变量。
java.lang.StringBuilder是一个可变的字符序列,是JDK5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍,因为线程不安全,所以一般只用在单线程下)。
StringBuilder初始化:
StringBuilder()
构造一个不带任何字符的字符串生成器,其初始容量为 16 个字符。
StringBuilder(CharSequence seq)
构造一个字符串生成器,它包含与指定的 CharSequence 相同的字符。
StringBuilder(int capacity)
构造一个不带任何字符的字符串生成器,其初始容量由 capacity 参数指定。
StringBuilder(String str)
构造一个字符串生成器,并初始化为指定的字符串内容。
三者比较:
1. 三者在执行速度方面的比较:StringBuilder > StringBuffer > String
String是不可变的对象, 因此在每次对String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,每次生成对象都会对占用内存,会对系统性能产生影响, 而原来的对象就会变为垃圾被GC回收掉。
StringBuffer每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。
StringBuilder 在单线程的情况下,执行速度比StringBuffer高。
2 . 使用策略:
1.如果要操作少量的数据用 String
2.单线程操作字符串缓冲区 下操作大量数据用StringBuilder
3.多线程操作字符串缓冲区 下操作大量数据用StringBuffer
4不要使用String类的"+"来进行频繁的拼接,因为那样的性能极差的。应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则。
3 可变性:
String 长度不可变,StringBuilder、StringBuffer可以改变
4、有无复写toString()
String 和StringBuilder复写了toString(),但是两者的复写方式是不同的。StringBuffer没有。
5.
String s2 = “This is only a”;
String s3 = “ simple”;
String s4 = “ test”;
String s1 = s2 + s3 + s4;
s2,s3,s4采用String定义,拼接时需要额外创建一个StringBuffer(或StringBuilder),依次追加到字符串后面,之后将StringBuffer转换为String;若采用StringBuffer(或StringBuilder),则不需额外创建StringBuffer。
6. StringBuilder一般使用在方法内部来完成类似"+"功能,因为是线程不安全的,所以用完以后可以丢弃。StringBuffer主要用在全局变量中。
7. 相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非确定系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,才可以采用StringBuilder;否则还是用StringBuffer。