String源码分析

  • 基于JDK1.8版本

1、类、接口、成员


// 不变类,可序列化,可内部比较,字符序列

public final class String
    implements java.io.Serializable, Comparable<String>,  {

    private final char value[];  // String是由char数组组成,由于设置为private final,且不提供公共方法获取,内部不可变由设计人员控制,故为不可变类。

    /** Cache the hash code for the string */
    private int hash; // 哈希码,初始默认值为0,由hashCode方法设置。

2、长度

    public int length() {
        return value.length; //返回字符数组长度
    }

3、是否为空

    public boolean isEmpty() {
        return value.length == 0; // 通过数组长度是否为0判断
    }

4、根据下标获取字符

    public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index); // 如果index小于0,或大于字符数组长度,抛出错误
        }
        return value[index]; // 直接通过下标访问数组元素
    }

5、和其他对象比较是否相等

    public boolean equals(Object anObject) {
        if (this == anObject) { // 直接通过==判断对象地址是否相等,若相等,即返回true
            return true;
        }
        if (anObject instanceof String) { // 判断对象是否为String类,若是,往下走
            String anotherString = (String)anObject; // 把Object转为String类
            int n = value.length; 
            if (n == anotherString.value.length) { // 判断两个String长度是否相等,若相等,比较数组中的字符是否相等
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) { // 从头遍历到尾部,一旦出现不相等的字符,就返回false
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true; // 完成遍历,说明相等
            }
        }
        return false; // anObject不属于String类
    }

6、忽略大小写进行相等比较

    public boolean equalsIgnoreCase(String anotherString) {
        return (this == anotherString) ? true
                : (anotherString != null)
                && (anotherString.value.length == value.length)
                && regionMatches(true, 0, anotherString, 0, value.length); // 进行匹配
    }

    public boolean regionMatches(boolean ignoreCase, int toffset, 
            String other, int ooffset, int len) {
        char ta[] = value;
        int to = toffset; // 起始位置
        char pa[] = other.value;
        int po = ooffset; // 起始位置
        // Note: toffset, ooffset, or len might be near -1>>>1.
        if ((ooffset < 0) || (toffset < 0)
                || (toffset > (long)value.length - len)
                || (ooffset > (long)other.value.length - len)) { // 起始位置合法性
            return false; 
        }
        while (len-- > 0) {
            char c1 = ta[to++];
            char c2 = pa[po++];
            if (c1 == c2) { // 开始判断字符,相等继续
                continue;
            }
            if (ignoreCase) { // 忽略大小写
                // If characters don't match but case may be ignored,
                // try converting both characters to uppercase.
                // If the results match, then the comparison scan should
                // continue.
                char u1 = Character.toUpperCase(c1); // 先同一进行大写转换
                char u2 = Character.toUpperCase(c2);
                if (u1 == u2) {
                    continue;
                }
                // Unfortunately, conversion to uppercase does not work properly
                // for the Georgian alphabet, which has strange rules about case
                // conversion.  So we need to make one last check before
                // exiting.
                // 转换为大写不能正常工作,我们需要做最后一次检查。
                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                    continue;
                }
            }
            return false;
        }
        return true;
    }

7、比较两个字符串词典

    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2); // 获取两个String中最小长度,比较完最小长度的字符便可判断出,谁排在前面
        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; // 前面相等,则比较长度,负数排在前面
    }

8、生成hash码

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函数式,推导公式val[0]*31^(n-1) + val[1]*31^(n-2) + ... + val[n-1],
                // 31为素数,根据素数的特性,与素数相乘得到的结果比其他方式更容易产生唯一性,也就是说产生 hash 值重复的概率比较小。
            }
            hash = h;
        }
        return h;
    }

9、

posted @ 2018-10-25 17:48  _sanjun  阅读(107)  评论(0编辑  收藏  举报