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类是不可变的即可了!
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android之获取手机上的图片和视频缩略图thumbnails
- android string.xml文件中的整型和string型代替
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Python动态类型的学习---引用的理解
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序