📜  Java中的String vs StringBuilder vs StringBuffer

📅  最后修改于: 2020-03-27 01:37:53             🧑  作者: Mango

先决条件:字符串初始化字符串
考虑以下具有三个串联函数的代码,该串联函数具有三种不同类型的参数:String,StringBuffer和StringBuilder。

// Java程序,展示String,StringBuilder和StringBuffer
class 芒果文档
{
    // 并联String
    public static void concat1(String s1)
    {
        s1 = s1 + "for芒果";
    }
    // 并联StringBuilder
    public static void concat2(StringBuilder s2)
    {
        s2.append("for芒果");
    }
    // 并联StringBuffer
    public static void concat3(StringBuffer s3)
    {
        s3.append("for芒果");
    }
    public static void main(String[] args)
    {
        String s1 = "芒果";
        concat1(s1);  // s1 没有改变
        System.out.println("String: " + s1);
        StringBuilder s2 = new StringBuilder("芒果");
        concat2(s2); // s2 改变了
        System.out.println("StringBuilder: " + s2);
        StringBuffer s3 = new StringBuffer("芒果");
        concat3(s3); // s3 改变了
        System.out.println("StringBuffer: " + s3);
    }
}

输出:

String: 芒果
StringBuilder: 芒果for芒果
StringBuffer: 芒果for芒果

说明:
1. Concat1:在此方法中,我们传递字符串“ 芒果”并执行“ s1 = s1 +” for芒果”。从main()传递的字符串未更改,这是由于String是不可变的。更改字符串的值将创建另一个对象,并且concat1()中的s1将存储对新字符串的引用。main()和cocat1()中的引用s1引用不同的字符串。
2. Concat2:在此方法中,我们传递字符串“ 芒果”并执行“ s2.append(“ for芒果”)”,该操作将字符串的实际值(在主目录中)更改为“芒果for芒果”。这是由于一个简单的事实,即StringBuilder是可变的,因此会更改其值。
2. Concat3:StringBuffer与StringBuilder相似,不同之处在于StringBuffer是线程安全的,即多个线程可以使用它而没有任何问题。线程安全性带来性能损失。

何时使用哪一个:

  • 如果字符串在整个程序中保持不变,请使用String类对象,因为String对象是不可变的。
  • 如果字符串可以更改(例如:字符串构造中的大量逻辑和操作)并且只能从单个线程访问,那么使用StringBuilder就足够了。
  • 如果字符串可以更改,并且可以从多个线程访问,请使用StringBuffer,因为StringBuffer是同步的,所以您具有线程安全性。

Java中字符串类型之间的转换

有时需要将不同类(例如String,StringBuffer,StringBuilder)的字符串对象相互转换。以下是一些可以做到这一点的技术。

  1. 从String到StringBuffer和StringBuilder:这很容易。我们可以直接将String类对象传递给StringBuffer和StringBuilder类构造函数。由于String类在Java中是不可变的,因此对于编辑字符串,我们可以通过将其转换为StringBuffer或StringBuilder类对象来执行相同的操作。下面是演示相同的Java程序。
    // Java从String到StringBuffer和StringBuilder的转换.
    public class Test
    {
        public static void main(String[] args)
        {
            String str = "芒果";
            // 从String到StringBuffer
            StringBuffer sbr = new StringBuffer(str);
            sbr.reverse();
            System.out.println(sbr);
            // 从String到StringBuilder
            StringBuilder sbl = new StringBuilder(str);
            sbl.append("For芒果");
            System.out.println(sbl);
        }
    }

    输出:

    果芒
    芒果For芒果
  2. 从StringBuffer和StringBuilder到String:可以使用toString()方法执行此转换,该方法在StringBuffer和StringBuilder类中都被重写。
    下面是演示的Java程序。请注意,虽然我们使用toString()方法,但会分配一个新的String对象(在Heap区域中)并将其初始化为StringBuffer对象当前表示的字符序列,这意味着对StringBuffer对象的后续更改不会影响String对象的内容。
    // Java展示从StringBuffer和StringBuilder到String.
    public class Test
    {
        public static void main(String[] args)
        {
            StringBuffer sbr = new StringBuffer("芒果");
            StringBuilder sbdr = new StringBuilder("Hello");
            // 从StringBuffer到String
            String str = sbr.toString();
            System.out.println("StringBuffer到String : ");
            System.out.println(str);
            // 从StringBuilder到String
            String str1 = sbdr.toString();
            System.out.println("StringBuilder到String : ");
            System.out.println(str1);
    
            sbr.append("For芒果");
            System.out.println(sbr);
            System.out.println(str);
        }
    }

    输出:

    StringBuffer到String :
    芒果
    StringBuilder到String :
    Hello
    芒果For芒果
    芒果
    
  3. 从StringBuffer到StringBuilder或反之:这种转换很棘手。没有直接的方法可以转换。在这种情况下,我们可以使用String类对象。我们首先使用toString()方法将StringBuffer/StringBuilder对象转换为String ,然后使用构造函数将StringBuffer/StringBuilder对象从String转换为StringBuilder/StringBuffer。
    // Java展示从StringBuffer到StringBuilder或反之.
    public class Test
    {
        public static void main(String[] args)
        {
            StringBuffer sbr = new StringBuffer("芒果");
            // 从StringBuffer到StringBuilder
            String str = sbr.toString();
            StringBuilder sbl = new StringBuilder(str);
            System.out.println(sbl);
        }
    }

    输出:

    芒果

结论:

  • String的对象是不可变的,StringBuffer和StringBuilder的对象是可变的。
  • StringBuffer和StringBuilder相似,但是对于单线程程序,StringBuilder更快,并且比StringBuffer更为可取。如果需要线程安全,则使用StringBuffer。