您的位置:首页 > 编程语言 > Java开发

String类 理解----final 不可变

2015-12-17 12:57 525 查看

String类理解-----不可变(final)

大家都知道String类是不可变的,String类是被final修饰过的类。final理解
不可变对象:一个对象在创建完成之后,不能在改变它的状态,那么这个对象就是不可变的。
-------------------------不能改变它的状态表示不能改变对象内的成员变量,包括基本数据类型的值,引用类型变量不能指向其他的对象。
下面有个例子我们来看下:
String cx ="abc";
System.out.println(cx);
cx = "nice";
System.out.println(cx);


输出结果:
abc
nice
这里大家基本都知道也很简单,但是它具体是怎么个原理呢?
首先创建一个String的对象,把值放入字符串常量池中。我们先让cx指向了abc值,然后又指向了nice值,从打印结果来看呢,我们所说的不可变对象已经变了。。。这里就是一个大的误区:cx是一个String对象的引用(引用数据类型),不是对象的本身。之所以变了 是变的cx的指向,上面一直用的是指向这个词语。
-------------------------------通过指向对象地址来访问对象的内容。
当我们指向nice的时候他会检测我们字符串常量池中是否有这个值,如果有那么直接就把这个对象的地址返回回来,没有则创建新的对象并返回地址。
所以说这个变的是cx的指向,而不是String对象本身!。

我们来看下1.7JAVA的String类源码:
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
这里我们可以看出其实String类就是对字符数组的封装。不过这个value他也是一个引用,指向的是一个数据对象。
cx-------char value[]------数组[a,b,c][n,i,c,e]
由于value他是私有的所以外部是无法修改它的。并且它还是final的,也就是说一旦String被初始化了,那么它就不能被改变了。

我们又来看一个例子:
String cx ="cx";
System.out.println(cx);
cx = cx.replace("c", "C");
System.out.println(cx);
输出结果:
cx
Cx
这里我们看到cx的值发生了改变,但是它的String对象却并没有改变的。原理:
当我们调用replace方法的时候,它的内部最后是返回了一个新的String对象给我们的,所以最开始cx所指向的String对象是没有改变的,只是返回了一个新的改变后的对象给我们,我们获取到输出了而已。
我们看下这个例子就能瞬间明了:

String cx ="cx";
System.out.println(cx);
cx.replace("c", "C");
System.out.println(cx);
输出结果;
cx
cx
结果是没有改变的,这就是为什么当我们使用replace、subString、toLowerCase等方法的时候它给我们返回了一个String对象的。
下面我们看下replace的源码:
public String replace(char oldChar, char newChar) {
if (oldChar != newChar) {
int len = count;
int i = -1;
char[] val = value; /* avoid getfield opcode */
int off = offset;   /* avoid getfield opcode */

while (++i < len) {
if (val[off + i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0 ; j < i ; j++) {
buf[j] = val[off+j];
}
while (i < len) {
char c = val[off + i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
<span style="color:#ff0000;">return new String(0, len, buf);</span>
}
}
return this;
}

看完之后大家也顿悟了吧。
不过呢,通过反射我们还是可以去对String类中的内容去进行改变的。这个就设计到了反射的概念了,我就不提了。我们一般也不会这样去做。
我们只需要理解到String类是不可变的即可了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  String JAVA 对象 class