【Java源码】String类

来源:互联网 发布:淘宝上vx号怎么添加 编辑:程序博客网 时间:2024/04/30 19:54

一、属性解读

/** The value is used for character storage. */    private final char value[];    /** The offset is the first index of the storage that is used. */    private final int offset;    /** The count is the number of characters in the String. */    private final int count;    /** Cache the hash code for the string */    private int hash; // Default to 0
1、String中使用字符数组value[]保存内容,由修饰final可知String一旦被赋值,它的内容就不能改变,这是String和StringBuilder、StringBuffer的主要区别;之前我以为是因为final修饰了String类造成了String不可变,这是错误的,final修饰类只是使类变成不可继承。由于value是不可变的,多个String对象可能会共享一个value中的值。

2、offset表示String对象的内容的起始字符在value[]中的偏移,因为多个对象可能公用一个value,所以有的对象可能只用了value的一部分字符。

比如:对于substring函数,就会直接将原串的value赋给子串,而只是变更子串的offset和count

 public String substring(int beginIndex, int endIndex) {if (beginIndex < 0) {    throw new StringIndexOutOfBoundsException(beginIndex);}if (endIndex > count) {    throw new StringIndexOutOfBoundsException(endIndex);}if (beginIndex > endIndex) {    throw new StringIndexOutOfBoundsException(endIndex - beginIndex);}return ((beginIndex == 0) && (endIndex == count)) ? this :    new String(offset + beginIndex, endIndex - beginIndex, value);//子串的offset和count变更    }String(int offset, int count, char value[]) {this.value = value;this.offset = offset;this.count = count;    }

又如,String(new StringBuilder(“xx").toString());

public String(StringBuilder builder) {        String result = builder.toString();        this.value = result.value;        this.count = result.count;        this.offset = result.offset;    }


3、count表示String对象的内容中字符的个数,它并不是指value[]的长度。所以,用count来判断对象内容是否为空或取长度。

public boolean isEmpty() {return count == 0;    }public int length() {        return count;    }
4、hash存储String对象的hashCode
 public int hashCode() {int h = hash;if (h == 0) {    int off = offset;//String的offset位置是对象第一个字符在value[]中的偏移    char val[] = value;    int len = count;            for (int i = 0; i < len; i++) {                h = 31*h + val[off++];//挨个将字符取出进行hash,这样相同字符串的hashCode肯定是一样的            }            hash = h;        }        return h;    }
对于equals方法,先比较对象的引用再比较字符
 public boolean equals(Object anObject) {if (this == anObject) {    return true;}if (anObject instanceof String) {    String anotherString = (String)anObject;    int n = count;    if (n == anotherString.count) {char v1[] = value;char v2[] = anotherString.value;int i = offset;int j = anotherString.offset;while (n-- != 0) {    if (v1[i++] != v2[j++])return false;}return true;    }}return false;    }

二、String对象的产生

1、直接引用常量池字符

String s1 = "Hello"; //将引用指向位于方法区的常量池中的“Hello”
2、使用常量池字符串构造

String s2 = new String("Hello");//创建新的对象,并将常量池中的值赋给它,对应源码方法如下:public String(String original) {int size = original.count;char[] originalValue = original.value;char[] v;  if (originalValue.length > size) {     // The array representing the String is bigger than the new     // String itself.  Perhaps this constructor is being called     // in order to trim the baggage, so make a copy of the array.            int off = original.offset;            v = Arrays.copyOfRange(originalValue, off, off+size); } else {//其实,若这个字符串在内存中是一个完整的char[],即不是某个value[]的一部分,则不需要赋值产生新的char[]     // The array representing the String is the same     // size as the String, so no point in making a copy.    v = originalValue; }this.offset = 0;this.count = size;this.value = v;    }
3、通过加号+产生字符串

3.1 常量字符的+

String s4 = "He" + "ll";//编译后为:String s4 = "Hell";
3.2 字符串对象+常量字符或字符串对象
String s5 = s1 + "XX";//编译后的代码为:String s5 = (new StringBuilder(String.valueOf(s1))).append("XX").toString();//实际产生了3个对象
3.2 常量字符串 + 常量字符或字符串对象

String s55 = "XX" + s1;//编译之后优化为(new StringBuilder("XX")).append(s1).toString();//产生了两个对象










0 0
原创粉丝点击