面试官:Java中操作字符串都有哪些类?它们之间有什么区别?
第一个问题答案:String、StringBuffer和StringBuiler
第二个问题答案:
1.StringBuffer 通过 synchronized 关键字的修饰,保证了资源不会被抢占,从而确保了线程安全。
应用场景:一般多线程优先考虑StringBuffer。
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
@Override
public synchronized StringBuffer append(int i) {
toStringCache = null;
super.append(i);
return this;
}
@Override
public synchronized StringBuffer append(long lng) {
toStringCache = null;
super.append(lng);
return this;
}
@Override
public synchronized StringBuffer append(float f) {
toStringCache = null;
super.append(f);
return this;
}
}
StringBuiler线程不安全,因为没有被synchronized修饰。
应用场景:一般单线程优先考虑(迭代必选StringBuiler)。
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
@Override
public StringBuilder append(int i) {
super.append(i);
return this;
}
@Override
public StringBuilder append(long lng) {
super.append(lng);
return this;
}
@Override
public StringBuilder append(float f) {
super.append(f);
return this;
}
}
2.StringBuffer和StringBuilder都继承自 AbstractStringBuiler类
总结:
StringBuffer和StringBuilder都继承自抽象类AbstractStringBuilder。
StringBuffer线程安全,StringBuiler线程不安全。
在使用场景上,多线程必选StringBuffer,单线程必选StringBuilder。
3.拼接字符串是三者的区别
- String是不可变对象(不能被继承),一旦创建,就不能修改它的值,每次操作必然产生一个新的对象。
- StringBuffer是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象。
- 连接字符串操作中StringBuffer的效率比String高
证明:+= 其实的通过StringBuilder实现的
public class StringTest {
public static void main(String[] args) {
String str = new String("hello,");
str+="world";
System.out.println(str);
}
}
毫无疑问结果都知道,那么具体+=如何实现拼接字符串的?
这里需要到反编译工具 jad。反编译工具细节请参考
沉默王二jad反编译工具
第一步:Windows+R -> cmd 通过命令 javac StringTest.java 生成StringTest.class文件
第二步:反编译 输入命令: jad StringTest.class ,生成StringTest.jad文件。
第三步:打开StringTest.jad文件。
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: StringTest.java
import java.io.PrintStream;
public class StringTest
{
public StringTest()
{
}
public static void main(String args[])
{
String s = new String("hello,");
s = (new StringBuilder()).append(s).append("world").toString();
System.out.println(s);
}
}
可以清楚的看到 += 如何实现拼接字符串。
new StringBuilder()).append(s).append("world").toString()
测试三者拼接字符串耗时。
public class StringTest {
static String wordStr = "abcdefghijklmnopqrstuvwxyz";//定义26个英文字母
static String str = "";//定义空字符串
static int count = 30000;//定义执行次数
public static void main(String[] args) {
System.out.println(time());
System.out.println(time2());
System.out.println(time3());
}
public static long time() {
long startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
str+=wordStr;
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
public static long time2() {
long startTime2 = System.currentTimeMillis();
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < count; i++) {
buffer.append(wordStr);
}
long endTime2 = System.currentTimeMillis();
return endTime2 - startTime2;
}
public static long time3() {
long startTime3 = System.currentTimeMillis();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < count; i++) {
builder.append(wordStr);
}
long endTime3 = System.currentTimeMillis();
return endTime3 - startTime3;
}
}
运行结果:
String耗时: 19977(19秒)
StringBuffer耗时:4(0.004秒)
StringBuilder耗时:3(0.003秒)
对于操作字符串的结论:StringBuilder > StringBuffer > String