Java String 类
String在Java编程中广泛的应用。Java程序中所有的字符串文本(如"abc")都是此类的实例。
String类的特点
- 字符串属于常量,他们的值在创建后就无法更改。也就是说他们创建是什么样最后还是什么样。由于字符串对象是不可变的,因此可以共享他们。
- 对于所有""字符串都是存放在堆中的字符串常量池
- 对String的重新赋值,会产生新的String对象,并且不会影响原来的值
- String属于引用数据类型,所以==比较的是引用值是否相等,String重写了equals方法来比较两个字符串是否相等。
- 通过new String("abc")时,"Hello"字面量字符串会先存放在字符串常量池中,然后通过new操作符创建一个新的字符串对象,并将该对象的值设置为"Hello"字面量字符串在常量池中的引用。
- 通过str.intern可以直接获取该字符串在字符串常量的引用。
源码解读
public final class String implements java.io.Serializable, | |
Comparable<String>, CharSequence |
Serializable:可序列化接口
Comparable:定义了比较规则接口
CharSequence :表示char值的一个可读序列
/** The value is used for character storage. */ | |
private final char value[]; | |
/** Cache the hash code for the string */ | |
private int hash; |
可以得到一些关键信息整个String类是final的,存储String的数组也被设计为final.
//构造函数 | |
public String() { | |
this.value = "".value; | |
} | |
public String(String original) { | |
this.value = original.value; | |
this.hash = original.hash; | |
} | |
public String(char value[]) { | |
this.value = Arrays.copyOf(value, value.length); | |
} | |
......省略 | |
//StringBuffer线程安全,加锁保证线程的安全性 | |
public String(StringBuffer buffer) { | |
synchronized(buffer) { | |
this.value = Arrays.copyOf(buffer.getValue(), buffer.length()); | |
} | |
} | |
//是否为空,判断通过长度 | |
public boolean isEmpty() { | |
return value.length == 0; | |
} | |
//索引 | |
public char charAt(int index) { | |
if ((index < 0) || (index >= value.length)) { | |
throw new StringIndexOutOfBoundsException(index); | |
} | |
return value[index]; | |
} | |
//字符串截取 | |
public String substring(int beginIndex){ | |
if (beginIndex < 0) { | |
throw new StringIndexOutOfBoundsException(beginIndex); | |
} | |
int subLen = value.length - beginIndex; | |
if (subLen < 0) { | |
throw new StringIndexOutOfBoundsException(subLen); | |
} | |
//通过new新实例的方法。包括replace,concat也是 | |
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); | |
} | |
public String concat(String str) { | |
if (str.isEmpty()) { | |
return this; | |
} | |
int len = value.length; | |
int otherLen = str.length(); | |
char buf[] = Arrays.copyOf(value, len + otherLen); | |
str.getChars(buf, len); | |
return new String(buf, true); | |
} | |
//重写 equals方法 | |
public boolean equals(Object anObject) { | |
if (this == anObject) { | |
return true; | |
} | |
if (anObject instanceof String) { | |
String anotherString = (String)anObject; | |
int n = value.length; | |
if (n == anotherString.value.length) { | |
char v1[] = value; | |
char v2[] = anotherString.value; | |
int i = 0; | |
while (n-- != 0) { | |
if (v1[i] != v2[i]) | |
return false; | |
i++; | |
} | |
return true; | |
} | |
} | |
return false; | |
} |
小结
String对象一旦创建就是不可变的,而且String对象的HashCode会被缓存起来,相关的操作都会产生一个新的不可变对象,并且新的对象不会影响原来的值。需要注意,由于字符串存放在字符串常量池,一块特殊的内存区域,因此应该避免在其中存储大量的字符串对象,以避免内存溢出的问题。同时可以减少new来创建字符串变量,减少在堆中创建新的字符串对象,使用字面量创建字符串可以节约内存空间。