Java中String、StringBuffer和StringBuilder的区别
在Java中String、StringBuffer和StringBuilder是处理字符串常用的类,三者都封装在java.lang包中,三者都被final修饰,所以不能被继承。所以主要从三者的可变性、性能和安全性讨论三者的不同:
三者的结构:
一、可变性
1、String:String为字符串常量,即String对象创建后不能被修改,每次对字符串操作都会产生新的对象,旧的对象会被GC回收。使用字符数组保存字符串:private final char value[ ];
(1)、以赋值方式创建时,会到Java方法空间的字符串常量池中寻找,如果没有则会创建一个并返回内存地址赋值给对象变量,如果有就返回字符串常量池中返回内存地址赋值给对象变量
(2)、以new方式创建时,则直接在堆中开辟空间,返回地址赋值给对象变量,不会去字符串常量池中寻找。
(3)、String对象的修改假象
1 String str = “hello”; 2 str=str + “world”; 3 System.out.println(str);
当我们执行上面上面代码是控制台输出:helloworld,String看似被修改了,其实这是个假象。整个执行过程是这样的:
- 执行String str = “hello”时,先创建一个str对象,在堆中开辟一个空间存放“hello”,并把内存地址赋值给str;
- 执行str = str + “world”时,先在堆内存中开辟新的空间存放“world”,然后再开辟新的内存空间存放str + “world”,即“hello world”,然后将“hello world”在堆中的内存地址返回赋值给str;
- System.out.println(str):输出。
2、StringBuffer与StringBuilder:可改变的Unicode字符序列,两者的对象是变量,对变量进行操作就是直接对该对象进行更改,而不会再次创建和回收的操作。使用字符数组保存字符串:char[ ] value;
(1)、创建时通过new初始化对象,通过对象调用相应方法;
(2)、StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
二、性能:StringBuilder > StringBuffer > String
1、StringBulder:没有实现线程安全功能,操作时不需要加锁,所以性能较高;
2、StringBuffer:实现了线程安全,在每次操作时都要判断锁,性能较StringBuilder慢;
3、String:每次操作时都会创建一个新的对象,从而经历了创建新对象,销毁旧对象的过程,所以性能最慢。
三、线程安全
1、StringBulder:没有实现线程安全功能,不具备多线程安全,但是在单线程情景下,性能最高;
2、StringBuffer:方法大都通过synchronized关键字修饰,实现了线程安全;
3、String:对象是不可变,通过final关键字修饰为一个常量,所以是线程安全的。
四、StringBuffer的初始化及扩容
1、StringBuffer():初始容量可以容纳16个字符,当该对象存放的字符大于16时,实体的容量会自动扩容,
2、StringBuffer(int size):可以指定该对象初始化容量为size长度的字符个数,当该对象存放的字符序列大于size时,实体的容量会自动扩容;
3、StringBuffer(String s):可以指定该对象的初始容量为该s字符串的长度再加上16个字符,当该对象存放的字符序列大于初始容量时,实体的容量会自动扩容;
StringBuffer对象可以通过length()方法获取实体中存放的字符序列长度,通过capacity()方法来获取当前实体的实际容量。
(五)、StringBuilder与StringBuffer的共同点
1、都有一个公共的AbstractStringBulder抽象类;
2、都会调用AbstractStringBuilder方法,如super.append(...),只是StringBuffer为了实现线程安全,会用关键字synchronized修饰;
3、都是final关键字修饰的类,不允许被继承。
(六)、总结
1、String:适用于字符串少量操作的情况;
2、StringBuffer:适用于在多线程环境下字符串大量操作的情况;
3、StringBuilder:适用于在单线程环境下字符串大量操作的情况。
以上是我自己平时学习的一个小知识点,如果有错误的地方,欢迎大家批评指正,谢谢!!