jdk源码阅读之String

String类

private final char value[];
private int hash; // Default to 0
private static final long serialVersionUID = -6849794470754667710L;
 private static final ObjectStreamField[] serialPersistentFields =
     		   new ObjectStreamField[0];

主要注意value和hash这两个域,String内部也是使用数组进行存储数据的,hash是这个字符串对应的哈希码,因为String是不可变的,当String的内容发生变化之后,虚拟机会生成一个新的字符串,并将String的引用只想这个字符串,这样如果String经常发生变化时,字符串常量表里面会有大量的字符串,会浪费内存,为了节约内存空间,一个方法是使用StringBuilder,StringBuilder是可变的,另一个方法就是为每一个不可变的字符串生成一个哈希码,这样如果字符串常量表中有现成的字符串时,就不需要再生成了,直接引用就行了。
为了验证常量字符串的缓存,举个例子:

public class TestDemo1 implements Cloneable {
	public static void main(String[] args) throws Exception {

		String a = "abc";
		String b = "abc";
		System.out.println(aString == bString);
	}
}

上面程序的最终结果为true.这也证明了a和b指向的是同一个对象,即常量池只有一个"abc"字符串。当然,上面成立的前提是直接将字符串常量赋值给String引用才有效,如果使用new的话,就会在堆中生成对象,即使使用一样的字符串初始化,引用也不会相等。

构造函数

    public String() {
        this.value = new char[0];
    }
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

不带参数的构造函数,实际上就是空,等价于

public String() {
        this.value = "".value;
    }

equals方法

String类对Object中equals方法进行了重写,判断的是两个String对象包含的字符串是否相等。

public boolean equals(Object anObject) {
        if (this == anObject) {	//如果是同一个引用,则直接返回true
            return true;
        }
        if (anObject instanceof String) { //如果anObject 为null,则instanceof返回false
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

compareTo方法

public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

String类实现了Comparable接口,所以说String是可比较的,compareTo的返回值是这样的,从两者的第一个字母比较过去,如果有一个字母不相等,则返回大的字母减去小的字母的int值,如果比较完了,则返回两者String的长度之差。符合compareTo方法的返回值要求,即:如果a小于b返回负数,如果a大于b,返回正数,否则返回0.

hashCode方法

public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

返回String对象的哈希码,并且把哈希码缓存在hash这个域中,避免每次调用都要重新计算。

substring方法

public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }
public String substring(int beginIndex, int endIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

返回当前String对象的子序列。

intern方法

public native String intern();

intern方法是一个本地方法,调用该方法,会判断是否常量池中有一个与该String对象相等的对象(也就是equals返回0),如果有返回常量池中的对象,否则,将该String对象添加到常量池中再返回常量池中的对象。
例如:

public class TestDemo1 implements Cloneable {
	public static void main(String[] args) throws Exception {
		String cString = "abc";
		String bString = new String("abc");
		String aString = bString.intern();
		System.out.println(cString == aString);    //返回的是true
	}
}

猜你喜欢

转载自blog.csdn.net/whoami_I/article/details/85986136