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

来源:互联网 发布:mac cmd 命令 编辑:程序博客网 时间:2024/04/27 20:27

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类是不可变的即可了!

0 0
原创粉丝点击