您的位置:首页 > 职场人生

黑马程序员【阅读源码理解String对象的不变性】

2014-07-09 16:51 405 查看
------- android培训java培训、期待与您交流! ----------

String的对象都有一个特性 ,就是不可变性,不可变是指String对象创建后,其值就不能再改变,代用String的任何方法修改字符串最后都会返回一个新的String对象,而对原String对象没有任何影响。下面通过解读源码和实例来进一步说明:

public class Test {
public static void main(String[] args) {
String s1="java";
String s2="heima";
String s11=s1.replace("a", "b");
String s22=s2.replace("h", "H");
//s1 s2的值不变
System.out.println(s1);
System.out.println(s2);
//修改后返回的一个新String对象
System.out.println(s11);
System.out.println(s22);
System.out.println(s1==s11);
System.out.println(s2==s22);
}
}

运行结果:

java

heima

jbvb

Heima

false

false

可以看到,通过replace方法并没能改变s1和s2的值,而且最终返回了一个新的String对象。

为什么不能直接修改String的变量呢?看一下String类的源码就一目了然了。

package java.lang;
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/**
*	String字符串的本质是一个字符数组
*	final限制了value引用是不可变的
*	同时用private修饰,又没有提供setter和getter方法,
*	最终决定了String类的不可变性
*
*/
private final char value[];
//构造方法,创建一个长度为0的空字符数组
public String() {
this.value = new char[0];
}
但是String类确实提供一些可以修改字符串的方法,concat,substring, replace, replaceAll等,可是从上面的例子中可以看出,最终并没有改变原字符串的值,这是为什么?

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 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;
}
不用管以上方法具体怎么实现的,只看最后的返回值,可以知道,都是用修改后的临时数组new一个新的String 返回给程序。
String类是不可变(final)的,对String类的任何改变,都是返回一个新的String类对象.这样的话把String类的引用传递给一个方法,该方法对String的任何改变,对原引用指向的对象没有任何影响。

------- android培训java培训、期待与您交流!

----------详情请查看:http://edu.csdn.net/heima
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: