java.lang.String源码分析(1)

来源:互联网 发布:劈叉的影响身高吗 知乎 编辑:程序博客网 时间:2024/05/22 03:25

java.lang.String类的源码分析

String类是java中比较常见的一个类,今天有空来看一下string的部分源码。
先构造一个string对象

String str = new String ("hello world!!!");

这句代码,查看源代码如下:

   public String(String original) {//传进来hello world    int size = original.count;//把长度赋值给size 这里是14     //这里的value是一个数组 private final char value[],    //用来存放character,应该是先把字符串转换成数组,再赋值给originalValue    char[] originalValue = original.value;    char[] v;    //如果新数组的长度大于size 把数组copy到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 {        // The array representing the String is the same        // size as the String, so no point in making a copy.       //这里执行是else中的语句        v = originalValue;    }    this.offset = 0;    this.count = size;    this.value = v;    }

debug模式下查看str对象的内容:
这里写图片描述

各个方法的源码:
1.str.length():返回此字符串的长度。

//不多说大家一看就懂 public int length() {        return count;    }

2.str.charAt(3):返回指定索引处的 char 值。

public char charAt(int index) {//将3传进来        //判断是否越界        if ((index < 0) || (index >= count)) {            throw new StringIndexOutOfBoundsException(index);        }        //直接返回index躲在位置上的字符,这里的offset是0        return value[index + offset];        }

3.str.compareTo(“123”):按字典顺序比较两个字符串

public int compareTo(String anotherString) {//123    int len1 = count;//str的字符串长度    int len2 = anotherString.count;//123的长度    int n = Math.min(len1, len2);//调用Math取最小值    char v1[] = value;//代表的是hello world!!!    char v2[] = anotherString.value;//123    int i = offset;//0    int j = anotherString.offset;//应该也是0    if (i == j) {//i==j时        int k = i;//k = 0        int lim = n + i;//lim = 3 +0,这里加上offset个人认为可能有时候需要从某个位置开始比较        while (k < lim) {//循环判断,直到找到第一个不相等的数值,返回两个字符的差值        char c1 = v1[k];        char c2 = v2[k];        if (c1 != c2) {            return c1 - c2;        }        k++;        }    } else {    //当指定了offset时,进入到这里        while (n-- != 0) {        //从指定的offset向后比较,找到第一个不相等的,返回差值        char c1 = v1[i++];        char c2 = v2[j++];        if (c1 != c2) {            return c1 - c2;        }        }    }    return len1 - len2;    }   

4.str.compareToIgnoreCase(“Hell”): 按字典顺序比较两个字符串,不考虑大小写,和上面的差不多 ,只是多了一部转换成相同的大小写

 public int compare(String s1, String s2) {            int n1=s1.length(), n2=s2.length();            for (int i1=0, i2=0; i1<n1 && i2<n2; i1++, i2++) {                char c1 = s1.charAt(i1);                char c2 = s2.charAt(i2);                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) {                            return c1 - c2;                        }                    }                }            }            return n1 - n2;        }    }

str.concat(“hello java”):将指定字符串连接到此字符串的结尾。

 public String concat(String str) { //得到新字符串的长度    int otherLen = str.length();    //如果长度为0直接返回原始字符串    if (otherLen == 0) {        return this;    }    //当str长度不为0时,重新定义一个新的字符数组    char buf[] = new char[count + otherLen];    //把老的字符串拷贝到buf里面    getChars(0, count, buf, 0);    //getchar源码如下:    /**     public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {        if (srcBegin < 0) {            throw new StringIndexOutOfBoundsException(srcBegin);        }        if (srcEnd > count) {            throw new StringIndexOutOfBoundsException(srcEnd);        }        if (srcBegin > srcEnd) {            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);        }    拷贝数组    各个参数的意思:1:要复制的数组             2:从那个位置开始复制             3:要复制到那个数组里面             4:复制到数组从第几个位置开始              5:复制的长度        System.arraycopy(value, offset + srcBegin, dst, dstBegin,             srcEnd - srcBegin);    }    */     //调用str的getChar把hello java 复制到数组buf里面    str.getChars(0, otherLen, buf, count);    //返回新数组,并重新定义相应的字段值    return new String(0, count + otherLen, buf);    }

str.contains(“llo”):当且仅当此字符串包含指定的 char 值序列时,返回 true。

     static int indexOf(char[] source, int sourceOffset, int sourceCount,                           char[] target, int targetOffset, int targetCount,                           int fromIndex) {         //当偏移量大于原始数组的长度,也就是说,target数组开始比较的位置比原始数组的长度还大,显然没法比较         if (fromIndex >= sourceCount) {            //目标数组的长度为0  返回原数组的长度,否则返回-1                return (targetCount == 0 ? sourceCount : -1);        }            if (fromIndex < 0) {                fromIndex = 0;            }            //如果你的目标数组是空字符串,这里也认为空字符串实在目标字符串中包含着的,会返回true        if (targetCount == 0) {            return fromIndex;        }            char first  = target[targetOffset];//从target的offset处开始比较            /**             * 最多比较的次数,这里比较经典,例如"hello world".contains("nihao");             * 因为偏移量是0所以方法会先比较h 和 n  不想等 继续向后走 直到走到 w 和 n 依然不想等 ,那么就不要再比较了 ,因为剩下的肯定就不会再相等了             */            int max = sourceOffset + (sourceCount - targetCount);            for (int i = sourceOffset + fromIndex; i <= max; i++) {               //第一个元素不想等                if (source[i] != first) {                    //进入while i++ 再次比较 第一个元素 知道相等在跳出while,这里采用++i为了减少第一个元素比较两次 ,赞                    while (++i <= max && source[i] != first);                }                /* Found first character, now look at the rest of v2 */                //如果第一个元素相等,并且i还小于max                if (i <= max) {                    int j = i + 1;//从下一个元素开始                    int end = j + targetCount - 1;                    //如果元素想等就一直向下走,直到遇到一个不想等的跳出for循环                    for (int k = targetOffset + 1; j < end && source[j] ==                             target[k]; j++, k++);                    //如果走到了目标元素的尾部,说明原数组中包含目标数组                    if (j == end) {                        /* Found whole string. */                        //返回匹配的第一个元素下标                        return i - sourceOffset;                    }                }                //否则继续向后走,知道下标越界跳出循环            }            return -1;        }
0 0
原创粉丝点击