Java源码剖析—2 String源码分析

接着上回String的源码分析:点击打开链接,此次接着分析String的源码进行分析


0 基础准备

静态内部类:当不需要内部类对象和外部类对象之间有联系,那么可以将内部类声明为static,静态内部类的实现不依赖域外部类的实例化,不论外部类的对象是否存在,都不影响内部类对象的实例化。


1-12 定义私有静态内部类— 忽略字符大小写的比较器

public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                         = new CaseInsensitiveComparator();

    /**
     * 大小写不敏感的比较器
     */
    private static class CaseInsensitiveComparator
            implements Comparator<String>, java.io.Serializable {
        // use serialVersionUID from JDK 1.2.2 for interoperability
        private static final long serialVersionUID = 8575799808933029326L;

        public int compare(String s1, String s2) {
            int n1 = s1.length();
            int n2 = s2.length();
            int min = Math.min(n1, n2);
            for (int i = 0; i < min; i++) {
                char c1 = s1.charAt(i);
                char c2 = s2.charAt(i);
                if (c1 != c2) {
                    c1 = Character.toUpperCase(c1);
                    c2 = Character.toUpperCase(c2);
                    if (c1 != c2) {
                        c1 = Character.toLowerCase(c1);
                        c2 = Character.toLowerCase(c2);
                        if (c1 != c2) {
                            // No overflow because of numeric promotion
                            return c1 - c2;
                        }
                    }
                }
            }
            return n1 - n2;
        }

        /** Replaces the de-serialized object. */
        private Object readResolve() { return CASE_INSENSITIVE_ORDER; }
    }


1-13  compareToIgnoreCase(String str)的实现是使用的1-12的忽略大小写的比较器,如果一个类中的比较器可以复用,建议使用String的私有静态内部类的方式,这样在外部类定义一个内部类引用,这样就可以在外部类中使用内部类的对象。

return CASE_INSENSITIVE_ORDER.compare(this, str);


1-14 substring(int beginIndex)
首先判断参数beginIndex的参数是否合法,然后使用的是String的一个构造函数String(char[] value,int offset,int count),这个从offset的位置开始,count个字符,进行构造成一个字符串。这个构造函数底层使用的是Arrays.copyOfRange方法,将原数据,拷贝到String对象的内部数组。


1-15 substring(int beginIndex.int endIndex)与1-14的方法不同就在于count值不同,有endIndex的方法,调用String的构造函数时,传递的是终止位序endIndex-startIndex的值

 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);
        }
        /**
         * 截取子串的方法使用的构造函数是String(char[] value,int offset,int count)
         * beginIndex是offset,count是endIndex-beginIndex
         */
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

1-16 concat:字符串拼接

    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        /** 字符数组拷贝,传递原数组和新数组的长度,创建一个新数组,把原数组的内容拷贝进去*/
        char buf[] = Arrays.copyOf(value, len + otherLen);
        /** str.getChars调用System.arraycopy(),将str的字符数组,从0开始到length,都拷贝到字符数组buf的后面,就实现了连接,底层调用System.arrayCopy */
        str.getChars(buf, len);
        return new String(buf, true);
    }

1-17 replace,替换字符串中的字符

   /**
     * 替换字符
     * @param oldChar 老字符
     * @param newChar 新字符
     * @return
     */
    public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {     /* 先找到第一次出现oldChar的位置,这样可以提高字符串中没有oldChar的情况的速度*/
                if (val[i] == oldChar) {
                    break;
                }
            }
            if (i < len) {      /* 有oldChar*/
                char buf[] = new char[len];
                for (int j = 0; j < i; j++) {
                    buf[j] = val[j];
                }
                while (i < len) { /* 比较后面一段的字符数组*/
                    char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);
            }
        }
        return this;
    }


1-18 matches(String regex) 匹配字符串是否符合正则表达式

public boolean matches(String regex) {
        return Pattern.matches(regex, this);
}


1-19 contains(CharSequence s) 返回是否包含字符串,方法的底层实现是indexOf(s) > -1来判断是否包含指定字符串


1-20 split(String regex,int limit) 分割


1-21 join(String delimetr,CharSequence... elements),第二个参数是可变参数,第一个参数连接符,第二个是字符序列,连接起字符序列后转成字符串。


1-22 各种valueOf方法,将各种类型转换成字符串类型


1-23 trim:去空字符串头部和尾部的空串

   /**
     * 去掉字符串前后的空字符
     * @return
     */
    public String trim() {
        int len = value.length;
        int st = 0;
        char[] val = value;    /* avoid getfield opcode */

        while ((st < len) && (val[st] <= ' ')) {    /*去掉头部asc码小于空格的码值(32)*/
            st++;
        }
        while ((st < len) && (val[len - 1] <= ' ')) { /*去掉尾部asc码小于空格的码值(32)*/
            len--;
        }
        return ((st > 0) || (len < value.length)) ? substring(st, len) : this;  /*头部或尾部有空格,取子串,否则返回原串*/
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值