String是java最常的类,但它不是基础类型--因而内存的堆栈中它是以地址的形式保存.而它有事一个很特殊引用类型:类的声明是final,它是不能被继承的:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence
String的主要属性:
private final char value[]; //String本质就是Char数组
private final int offset; //起始位?这个变量没明白,不过可看作数字0
private final int count; //就是Sting的length
private int hash; //hash码
StringBuffer的重要属性:
char value[];
int count;
非常好!String的属性基本都是final类型,这应该就是Think In Java里的恒常性的关键所在.
对于final我们可以这样理解:
- 若变量是基本类型则它的值是不能变的。
- 若变量是对象则它的索引指向(在堆栈中)不可变,而只可能改变索引指定的对象(堆中)内的值。
而由于String内部变量是Final所以String的变量的索引指向不能变,而Char数组又是长度固定(String的改变往往带来长度的变化)。所以对String的改变不能将原来的String改变(原来的String的value指定被锁死),而只能重新返回一个新的String.这就是String与其他普通对象的重要区别---对其任何的本质上的改变都不会改变对象本身,而是返回一个新的对象.
StringBuffer由于不是final因而对StringBuffer的值改变只需要将类里的value[]的指向重新定向即可而不用重新new一个StringBuffer返回
String的构造器
public String()
{
offset = 0;
count = 0;
value = new char[0];//这个为什么不设置为null? 感觉是由于String有"+"操作,而null不可能有"+"操作
}
String的equals方法---由于char本质是数字因而直接==比较。
public boolean equals(Object obj)
{
if(this == obj)
return true;
if(obj instanceof String)
{
String s = (String)obj; int i = count;
if(i == s.count)
{
char ac[] = value; char ac1[] = s.value;
int j = offset; int k = s.offset;
while(i-- != 0) //值得学习 非常的精巧
if(ac[j++] != ac1[k++])
return false;
return true;
}
}
return false;
}
在看完string源码后感觉String的本质就是Char[],他所有的方法都围绕着数组.而且虽然String有大量的方法不过一般背后都有一个通用方法,而其他方法都是调用这个通用方法实现的.而这里感觉最好的就是:
while(i-- != 0)
简直精巧极了!这可能就是代码的优雅.
总结:想看String的源码就是因为Think In Java所说的恒常性.而String的实现比较简单---重要变量为final形式