Concurrent Work

Rambling of a coder who craves for knowledge and understanding of the world.

Written by Dongfang Qu

08 Mar 2014

java String 详解

Java可表达字符串的类主要有java.lang.String, java.lang.StringBuffer和java.lang.StringBuilder三种,下面介绍一下它们三者的异同;

java.lang.String

字符串常量,只读,每次赋值操作会destroy掉原有对象重新创建,修改代价大,适用于表达只读字符串变量,线程安全。

java.lang.StringBuilder

字符串变量,可修改,类似于C/C++的字符串,支持字符串编辑,delete/insert等方法,适用于字符串编辑操作,非线程安全。

java.lang.StringBuffer

java.lang.StringBuilder的线程安全版本,适用于多线程环境下对字符串的编辑修改。

String 传参

String是引用类型,在函数调用中是按引用传递参数,但是String是final类型的,定长,不允许对其进行改变,函数调用里面对String类型变量的赋值操作事实上是创建了一个新的String变量;所以函数调用中对String类型变量的修改不会影响函数体外变量的值。

// StringUsage.java

package String;

import java.lang.String;
import java.lang.StringBuffer;
import java.lang.StringBuilder;

public class StringUsage {
    public static void main(String[] args) {

        String str1 = "string"; // 在栈上分配,静态变量区,同一个字符串只有一个副本
        String str2 = "string";
        String str3 = new String("string"); // 在堆上分配,单独创建一个对象
        String str4 = new String("string");

        System.out.println(str1 == str2); // true, str1和str2指向相同的内存地址
        System.out.println(str2 == str3); // false, str2和str3指向的内存地址不同
        System.out.println(str3 == str4); // false, str3和str4指向不同的内存对象
        str3 = str3.intern(); // String.intern() 在常量池创一个值和str3相同的字符串返回,如果常量池已存则直接返回存在的地址
        System.out.println(str3 == str1); // true

        // 理论上修改操作的性能应该是:String << StringBuffer < StringBuilder
        long start = 0, end = 0;
        start = System.currentTimeMillis();
        for(int i = 0; i < 100000; i++)
        {
            str1+= "test";
        }
        end = System.currentTimeMillis();
        System.out.println("consumed: " + (end -start) + " ms");
        // consumed: 8925 ms

        StringBuffer stringBuffer = new StringBuffer("string buffer");
        start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            stringBuffer.append("test");
        }
        end = System.currentTimeMillis();
        System.out.println("consumed: " + (end - start) + " ms");
        // consumed: 10 ms

        StringBuilder stringBuilder = new StringBuilder("string builder");
        start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            stringBuilder.append("test");
        }
        end = System.currentTimeMillis();
        System.out.println("consumed: " + (end - start) + " ms");
        // consumed: 5 ms

    }
}

Categories

Tags