* @author Lee Boynton
* @author Arthur van Hoff
* @version %I%, %G%
* @see java.lang.Object#toString()
* @see java.lang.StringBuffer
* @see java.lang.StringBuilder
* @see java.nio.charset.Charset
* @since JDK1.0
*/
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
{
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
/** Cache the hash code for the string */
private int hash; // Default to 0
Sring使用 final char value[ ] 存储字符串内容。即当一个String对象创建完毕后,该对象值已不可修改。故String被称为不可变类型。
String常量池:虚拟机中类似一张全局String列表,其中元素唯一,使用“”双引号创建String对象将保存于常量池,此方式创建对象时先检查常量池中是否存在该字符串对象,存在返回引用,不存在创建再返回。用于提高效率。
String对象两种创建方式:
1, new String(“abcd”):此处创建两个String对象:new String(),"abcd" ,前者存储于堆内存,后者存于常量池(见下测试1)。
2,“abcd”: 直接使用双引号创建String对象保存于字符串常量池。
String对于+运算符的重载:
1: “ab”+"cd"
String s1 = "ab" + "cd";
String s2 = "abcd";
syso(s1 == s2);
print: true;
此方式生成第三个字符串"abcd",存于常量池。
2:
String s1 = "ab";
String s2 = s1 + "cd";
syso(s2.intern() == s2);
print: false
此方式生成字符串存在于堆内存;
测试1: new String("Demo"), 参数字符串存储于常量池 or 堆内存?
修改String源码如下
注:intern()方法:查找常量池中是否有相同字符串常量,有则返回其引用,没有则在常量池中创建新String并返回引用。
编译class,覆盖rt.jar文件。
public String(String original) {
String tmp = original.intern();
System.out.println(tmp == original? "存于常量池" : "未存于常量池");
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
// The array representing the String is bigger than the new
// String itself. Perhaps this constructor is being called
// in order to trim the baggage, so make a copy of the array.
int off = original.offset;
v = Arrays.copyOfRange(originalValue, off, off+size);
} else {
// The array representing the String is the same
// size as the String, so no point in making a copy.
v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
}
测试代码:
public class StringDemo {
public static void main(String[] args) {
new String("haha");
}
}
结果打印:存于常量池
StringBuilder,StringBuffer效率提高在哪:
这两个类维护非final字符数组,用于连续添增字符拼接,避免了使用String类型+运算符生成很多多余无用的String对象.且字符串常量池常驻内存,生命周期较长,故节省内存了开支。但append(String)方法中 并没有避免参数String对象的创建.且此处String对象存储于常量池。
新手,有错误请指教。谢谢。
whanche@126.com 欢迎交流。