String源码java
public final class String implements java.io.Serializable, Comparable<String>, 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 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;app
String s = "hello"; for(int i = 0;i < 1000;i++){ s += "world"; }
上面这段代码是经过String直接操做的,那么根据以前分析的String的特性可知:每执行一步 "+" 操做,须要先建立一个新的对象,而后将原对象赋值给新对象,而后在新对象上进行 "+"操做,而后再将新对象返回。以此类推...,执行完上面的代码须要建立 1000 个新对象,很浪费空间。ui
StringBuilder sb = new StringBuilder("hello"); for(int i = 0;i < 1000;i++){ sb.append("world"); }
上面这段代码只会建立一个对象,即StingBuilder,它的操做字符串效果是在原对象上进行的,不会浪费太多空间。this
经过查看源码发现StringBuilder 和 StringBuffer的成员变量和方法大体相同,只不过StringBuffer 在方法上加入了同步关键字:synchronized,也就是说StringBuffer提供了多线程访问线程安全策略,是线程安全的。那么从这里可知:线程
StringBuilder 执行效率快,线程不安全;StringBuffer执行慢,线程安全。code