String&StringBuilder&StringBuffer

String 基础

String源码


public final class String
    implements java.io.Serializable, Comparable, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /**
     * Initializes a newly created {@code String} object so that it represents
     * an empty character sequence.  Note that use of this constructor is
     * unnecessary since Strings are immutable.
     */
    public String() {
        this.value = "".value;
    }
    ...
    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }

    public String substring(int beginIndex, int endIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

    public CharSequence subSequence(int beginIndex, int endIndex) {
        return this.substring(beginIndex, endIndex);
    }

    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

    public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {
                if (val[i] == oldChar) {
                    break;
                }
            }
            if (i < len) {
                char buf[] = new char[len];
                for (int j = 0; j < i; j++) {
                    buf[j] = val[j];
                }
                while (i < len) {
                    char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }

分析源码:
1.String 类为 final 修饰,说明该类不能被重写。 2.String类型的字符串其实是以 字符的形式存储的,(private final char value[]) 3.任何操作字符串的方法都是建立在新的字符串之上的,字符串的操作不会影响到原来的字符串对象,而是新建一个字符串副本以供操作。

String & StringBuilder&StringBuffer

String

String s1 = "daxiong"; String s2 = "daxiong"; String s3 = new String("daxiong"); String s4 = new String("daxiong");

JVM 内存机制中针对不同的属性进行不同的分区存储。字面量以及符号都会存在于方法区的常量池中,这里以HotSpot虚拟机为例,那么 String s1 = "daxiong"; 其中 "daxiong" 字面量就会存储到方法区的常量池中,当执行到 Stirng s2 = "daixong";的时候虚拟机会到方法区的常量池中进行检测,如果检测到常量池中存在"daxiong",那么就不会再次创建,如果没有检测到,则会重新创建,这里很显然已经存在,则不会再次创建新的"daxiong"。而对于String s3 = new String("daxiong");JVM专门分配一块内存区域叫做堆来存储对象实例,也就是通过new关键字创建的对象(注意:随着技术的发展,当前的虚拟机不是所有的通过new关键字创建的实例都会放到堆中),那么s3这个实例对象就会在堆上被分配内存空间,当然String s4 = new String("daixong");也同样会在堆上被分配内存空间。而这两者的引用都会存储到栈空间,栈空间又分为JVM虚拟机栈和本地方法栈两类,上面的实例的引用都在JVM虚拟机栈中存储。所以综上所述:s1 == s2,s1 != s3/s4,s3 != s4;

StringBuilder

String s = "hello";
for(int i = 0;i < 1000;i++){
    s += "world";
}

上面这段代码是通过String直接操作的,那么根据之前分析的String的特性可知:每执行一步 "+" 操作,需要先创建一个新的对象,然后将原对象赋值给新对象,然后在新对象上进行 "+"操作,然后再将新对象返回。以此类推...,执行完上面的代码需要创建 1000 个新对象,很浪费空间。

StringBuilder sb = new StringBuilder("hello");
for(int i = 0;i < 1000;i++){
    sb.append("world");
}

上面这段代码只会创建一个对象,即StingBuilder,它的操作字符串效果是在原对象上进行的,不会浪费太多空间。

StringBuffer

通过查看源码发现StringBuilder 和 StringBuffer的成员变量和方法大致相同,只不过StringBuffer 在方法上加入了同步关键字:synchronized,也就是说StringBuffer提供了多线程访问线程安全策略,是线程安全的。那么从这里可知:

StringBuilder 执行效率快,线程不安全;StringBuffer执行慢,线程安全。

转载于:https://my.oschina.net/u/3757468/blog/1837342

你可能感兴趣的:(String&StringBuilder&StringBuffer)