面试题——————String、StringBuffer和StringBuiler的区别

面试官: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.拼接字符串是三者的区别

  1. String是不可变对象(不能被继承),一旦创建,就不能修改它的值,每次操作必然产生一个新的对象。
  2. StringBuffer是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象。
  3. 连接字符串操作中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

猜你喜欢

转载自blog.csdn.net/lirui1212/article/details/115336425
今日推荐