2020-09-12(String类(与正则表达式相关的暂无))(附源码+个人分析观点)

String 类:(暂留:split()和replace()方法,以及new String(char[] a, boolean b) )

private final char value[];

String类中定义了一个私有的最终的char类型数组,
本质上就是把创建的String类型的字符串存进value[]数组中。
因为是final修饰,所以后面不可更改。

一.构造方法(new 初始化对象的时候使用)

 1.public String(),初始化一个新创建的 String 对象,使其表示一个空字符序列。注意,由于 String 是不可变的,所以无需使用此构造方法。

2.public String(String str),丢一个String字符串,初始化一个新创建的String对象,使其表示一个与参数相同的字符序列。

String s = new String("abc");

源码:
public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
}
new一个String类对象,调用一个有参的构造函数把"abc"当作形参丢进去,
然后再把"abc"传进char类型数组value中

3.String(char[] cs),丢进去一个字符数组,初始化一个String对象。

char[] a = {'a','b','c','d','e'};
String s = new String(a);

源码:
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}
由此可见,新创建的字符串是参数字符串的副本,
所以,随后的修改字符数组不会影响新创建的字符串。

4.String(char[] cs, int offset, int count),丢进去一个字符数组和两个int类型常量,offset表示从字符数组的这个下标开始,count表示选中多少个字符,从而初始化一个String对象。(同理可以传入其他数组)

char[] a = {'a','b','c','d','e'};
String s = new String(a,1,2);
System.out.println(s);//bc

源码:
 public String(char value[], int offset, int count) {
        if (offset < 0) {    //开始下标小于0,便会抛出异常
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {    
            if (count < 0) {  //复制的长度小于0,也会抛出异常
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) { //复制的长度为0,并且开始下标不长于目标数组的长度
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1. 
        // 注意:偏移量或计数可能接近-1>>>1。
        if (offset > value.length - count) { //判断后面的内容够不够复制的
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        //都没有错才会把数组复制一份
        this.value = Arrays.copyOfRange(value, offset, offset+count);
  }


特殊的,当传入的数组为int类型时:
由于不是所有的Unicode字符都能用16bit(java中char是16bit)表示,
所以CodePoints参数为int数组,并且在构造函数中需要转换才能存入char value[] 中。

源码:
    public String(int[] codePoints, int offset, int count) {
        //这些都和前面一样,但是对于int类型数组,加了以下判断
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= codePoints.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > codePoints.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }



        final int end = offset + count;//确定要复制到哪里

        // Pass 1: Compute precise size of char[]
        // 第1步:计算char[]的精确大小
        int n = count; //接受复制之后数组的长度
        for (int i = offset; i < end; i++) { //遍历将要复制的数组(不是全部,从要复制的开始)
            int c = codePoints[i];
            if (Character.isBmpCodePoint(c))  //传进的参数是否在Bmp中?
                continue;
            else if (Character.isValidCodePoint(c)) //传进的参数是否在Valid中?
                n++;               //如果是的就可以用一个char保存,否则要用两个
            else throw new IllegalArgumentException(Integer.toString(c)); //不然就抛出异常
        }

        // Pass 2: Allocate and fill in char[]
        // 第2步:分配和填充char[]
        final char[] v = new char[n];

        for (int i = offset, j = 0; i < end; i++, j++) {
            int c = codePoints[i];
            if (Character.isBmpCodePoint(c)) //只有数组中的内容(int)在Bmp中,才会复制
                v[j] = (char)c;
            else
                Character.toSurrogates(c, v, j++);//如果不在,就调用toSurrogates方法
        }

        this.value = v;//因为是构造函数,所以要把结果返回给String类中定义的value数组
    }


补充:

1个java的char字符并不完全等于一个unicode的字符。java只好对后来新增的unicode字符用2个char拼出1个unicode字符。导致String中char的数量不等于unicode字符的数量。
codePointCount()就是准确计算unicode字符的数量,而不是char的数量。

Character.isBmpCodePoint(c):编码点要测试的字符(Unicode编码点)
 public static boolean isBmpCodePoint(int codePoint) {
        return codePoint >>> 16 == 0;
        //表示不带符号向右移动二进制数,移动后前面统统补0;两个箭头表示带符号移动
 }


Character.isValidCodePoint(c):要测试的Unicode代码点
 public static boolean isValidCodePoint(int codePoint) {
        // Optimized form of:
        //     codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT
        int plane = codePoint >>> 16;
        return plane < ((MAX_CODE_POINT + 1) >>> 16);
}

static void toSurrogates(int codePoint, char[] dst, int index) {
        // We write elements "backwards" to guarantee all-or-nothing
        //我们“向后”写入元素,以保证要么全有要么全无
        dst[index+1] = lowSurrogate(codePoint);
        dst[index] = highSurrogate(codePoint);
}

5.String(byte[] bs)和String(byte[] bs,int offset, int count),同3,4一样,只是丢进去的数组不一样,根据ASCALL码变化。

byte[] a={97,98,99,100,101};
String s=new String(a);
String s1 = new String(a,1,2);
System.out.println(s);//abcde
System.out.println(s1);//bc

	
A:65  Z:90
a:97  z:122

6.String(byte[] bytes, String charsetname),丢进去一个byte数组和一个指定的charset解码去构建一个新的字符串对象。

二.常用的成员方法(使用字符串"."方法名调用)

注意:为方便对字符串处理,String 类提供了大量的方法。需要注意的是这些方法都不会对字符串本身做修改,而是返回处理结果,或者处理完成后,返回处理后的新字符串。

(这些方法有的会丢进去一个字符串,然后在底层会先转换成char类型数组,然后只要参与比较(大多数为循环),就要判断长度为负数,或者长度越界问题(底层实现了))

1.public int length(),返回调用此方法的字符串的长度。

String a="abcdef";
int length=a.length();
System.out.println(length); //6

源码:
public int length() {
    return value.length;
}

数组中.length是属性,字符串中.length()是方法

2.public int indexOf(char c)// 返回c字符在字符串第一次出现的下标
   public int indexOf(String c)// 返回字符串c在字符串第一次出现的下标
   public int indexOf(String c,int fromIndex)// 返回字符串c在字符串在formIndex(包含)后第一次出现的下标
   public int indexOf(char c,int fromIndex)// 返回字符c在字符串在formIndex(包含)后第一次出现的下标

String a = "abcdef123ghabcdef";
int indexOf = a.indexOf('d');
System.out.println(indexOf); //3
int indexOf2 = a.indexOf('d', 3); //3,看出来是包含传进去的这个形参的
System.out.println(indexOf2);
int indexOf3 = a.indexOf('d',4);
System.out.println(indexOf3); //14
int indexOf4 = a.indexOf("cde");
System.out.println(indexOf4); //2
int indexOf5 = a.indexOf("cde",3);
System.out.println(indexOf5);  //13

注意:
1.丢进去的形参:fromIndex,是包含这个位置的,从这个位置开始,
2.数组是从0开始算起,不是1
3.此方法返回值不要忘记,记得要用一个int类型变量接受。
4.当查询的值在字符串中不存在的话,则返回-1

源码:(可以看出,底层都是参数少的方法在调用参数多的方法,即重载,提高了代码的可复用性)
    public int indexOf(String str) {
        return indexOf(str, 0);
    }

    public int indexOf(String str, int fromIndex) {
        return indexOf(value, 0, value.length,
                str.value, 0, str.value.length, fromIndex);
    }

    个形参的含义:
    char[] source:源字符串(数组)
    int sourceOffset:从源字符数组的哪个下标开始搜索
    int sourceCount:源字符串(数组)的长度
    char[] target:指定要搜索的字符,或者字符串(数组)
    int targetOffset:从要搜索的字符串(数组)的下标(一般为0)
    int targetCount:要搜索的字符串(数组)的长度(可定长)
    int fromIndex:开始搜索的下标

    static int indexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        if (fromIndex >= sourceCount) {
            return (targetCount == 0 ? sourceCount : -1); //返回-1表示没找到
        }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
        if (targetCount == 0) {  //要搜索数组长度为0
            return fromIndex;
        }

        char first = target[targetOffset];//把要搜索的字符串(数组)的第一个字符提取出来
        // 找到需要遍历的最大位置
        int max = sourceOffset + (sourceCount - targetCount);

        for (int i = sourceOffset + fromIndex; i <= max; i++) {
            /* Look for first character. */
            // 找到第一个相等字符的位置,不相等就一直加,注意边界
            if (source[i] != first) {
                while (++i <= max && source[i] != first);
            }

            /* Found first character, now look at the rest of v2 */
            // 找到第一个字符,现在看看v2的剩余部分
            if (i <= max) {
                int j = i + 1;
                int end = j + targetCount - 1;
                
                // 循环遍历,找到全部相同的
                for (int k = targetOffset + 1; j < end && source[j]
                        == target[k]; j++, k++);

                if (j == end) {
                    /* Found whole string. */ //找到这个字符串
                    return i - sourceOffset;
                }
            }
        }
        return -1;
    }

例如:
String s = "97653287541";
String s1 = "287";
int indexOf = s.indexOf(s1);

s.indexOf(s1)-->s.indexOf(s1,0)-->s.indexOf(s,0,s.length(),s1,0,s1.length(),0)
其实好多参数都不是给这里用的。

3.public int lastIndexOf(char c);//判断字符c在字符串中最后一次出现的下标
   public int lastIndexOf(String str);//判断字符串str在字符串中最后一次出现的下标
   public int lastIndexOf(char ch, int fromIndex);//判断字符c在字符串从第fromIndex(包含)之前中最后一次出现的下标
   public int lastIndexOf(String str, int fromIndex);//判断字符串str在字符串从第fromIndex(包含)之前中最后一次出现的下标

String a = "abcdef123ghabcdef";
int indexOf = a.lastIndexOf('d');
System.out.println(indexOf); //14
int indexOf2 = a.lastIndexOf('d', 3); //3
System.out.println(indexOf2);
int indexOf3 = a.lastIndexOf('d',4);
System.out.println(indexOf3); //3
int indexOf4 = a.lastIndexOf("cde");
System.out.println(indexOf4); //13
int indexOf5 = a.lastIndexOf("cde",3);
System.out.println(indexOf5);  //2

源码:(没研究)
    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        /*
         * Check arguments; return immediately where possible. For
         * consistency, don't check for null str.
         */
        int rightIndex = sourceCount - targetCount;
        if (fromIndex < 0) {
            return -1;
        }
        if (fromIndex > rightIndex) {
            fromIndex = rightIndex;
        }
        /* Empty string always matches. */
        if (targetCount == 0) {
            return fromIndex;
        }

        int strLastIndex = targetOffset + targetCount - 1;
        char strLastChar = target[strLastIndex];
        int min = sourceOffset + targetCount - 1;
        int i = min + fromIndex;

    startSearchForLastChar:
        while (true) {
            while (i >= min && source[i] != strLastChar) {
                i--;
            }
            if (i < min) {
                return -1;
            }
            int j = i - 1;
            int start = j - (targetCount - 1);
            int k = strLastIndex - 1;

            while (j > start) {
                if (source[j--] != target[k--]) {
                    i--;
                    continue startSearchForLastChar;
                }
            }
            return start - sourceOffset + 1;
        }
    }

4.public char charAt(int index),返回指定索引处的 char 值。索引范围为从 0length() - 1

String s = new String("abcde");
char charAt = s.charAt(3);
System.out.println(charAt);//d

源码:
public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) { //防止下标越界
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}
		

5.public boolean contains(String str),当且仅当此字符串包含指定的 str字符串序列时,返回 true。

String s = new String("abcde");
boolean contains = s.contains("a");
System.out.println(contains); //true

源码:
    public boolean contains(CharSequence s) {
        return indexOf(s.toString()) > -1;
    }

6.public boolean isEmpty(),当且仅当 length() 为 0 时返回 true。

String s = "sasd";
String s1 = "";
String s2 = null; //报错
		
System.out.println(s.isEmpty());//false
System.out.println(s1.isEmpty());//true
System.out.println(s2.isEmpty());//NullPointerException

源码:
public boolean isEmpty() {
    return value.length == 0;
}


注意:只有双引号才算空,有空格也不算空,另外,当为null的时候会报错。

7.public boolean startsWith(String str)    测试此字符串是否以指定的前缀开始。                                                                               public boolean endsWith(String str)     测试此字符串是否以指定的后缀结束。

String a = "abcdef123ghabcdef";
System.out.println(a.startsWith("a")); //true
System.out.println(a.startsWith("abc"));//true
System.out.println(a.startsWith("abd"));//false
		
System.out.println(a.endsWith("f"));  //true
System.out.println(a.endsWith("ef")); //true
System.out.println(a.endsWith("abc"));//false


源码:
    prefix:判断是不是以这个字符串开头或结尾
    toffset:从字符串(字符数组)的哪个下标开始,不写默认为0


    public boolean startsWith(String prefix) {
        return startsWith(prefix, 0);
    }


    public boolean startsWith(String prefix, int toffset) {
        char ta[] = value; //调用这个方法的那个字符串(数组)用char ta[]接收
        int to = toffset;
        char pa[] = prefix.value;//把传进来的形参转换为char数组,并用char pa[]接收
        int po = 0;
        int pc = prefix.value.length;
        // Note: toffset might be near -1>>>1.//注意:开始比较的那个位置不能小于0
        if ((toffset < 0) || (toffset > value.length - pc)) {
            return false;
        }
        while (--pc >= 0) {  //控制的是形参字符串(上面转换为char数组了)的长度
            if (ta[to++] != pa[po++]) {   //挨个判断,有一个不等就返回false
                return false;
            }
        }
        return true;
    }

    //endsWith()底层也是调用startsWith()方法,只是传进去的参数做了改变。
    public boolean endsWith(String suffix) {
        return startsWith(suffix, value.length - suffix.value.length);
    }
    // value.length - suffix.value.length
    // 用源字符串(数组)长度 减去 要比较字符串(数组)的长度,结果即为最后的位置,正好比较完

8. public boolean equals(String str),判断字符串的内容是否相等                                                                                                          public boolean equalsIgnoreCase(String str);判断字符串的内容是否相等不区分大小写。  

当字符串和常量进行比较
错误写法:str.equals("张三");
正确写法:"张三".equals(str);

源码:(String类中重写了.equals方法,所以判断的是内容)
 public boolean equals(Object anObject) {
      if (this == anObject) { //"=="判断内存地址
          return true;
      }
      if (anObject instanceof String) { //向下转型
          String anotherString = (String)anObject;//强转
          int n = value.length;
          if (n == anotherString.value.length) { //判断长度,若不等直接返回false
              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;
 }


源码:
public boolean equalsIgnoreCase(String anotherString) {
      return (this == anotherString) ? true
           : (anotherString != null)
           && (anotherString.value.length == value.length)
           && regionMatches(true, 0, anotherString, 0, value.length);
}

//这里运用了三目运算符,如果两个数组内存地址相等,直接返回true,
//否则,要满足一下三点才返回true,否则返会false
//       1.传进来的数组不为空
//       2.两个数组的长度相同
//       3.调用regionMatches()方法且返回的是true

regionMatches()方法源码:
    各形参所代表的含义:
        ignoreCase:如果是true。在比较的时候忽略大小写,
        toffset:源字符串(构造方法转换为char数组了)开始比较的下标
        other:要被比较的字符串(char数组)
        ooffset:要被比较的字符串(char数组)开始比较的下标
        len:要被比较的字符数
    public boolean regionMatches(boolean ignoreCase, int toffset,
            String other, int ooffset, int len) {
        char ta[] = value; //用char ta[]接收源字符串
        int to = toffset;
        char pa[] = other.value; //Srting类型字符串+.value转换为字符数组
        int po = ooffset;
        // Note: toffset, ooffset, or len might be near -1>>>1.
        // 注意:toffset, ooffset, or len这三个值不能小于0 (大概意思)
        /*
         *两个比较的字符串(char数组)开始比较的位置有一个下标小于0
         *或者要比较的长度超过本来数组的长度,即越界,只要有一个成立就返回false
         * toffset > (long)value.length - len)可以理解为:
         * (toffset + len) > value.length 即开始比较的下标+要比较长度>数组长度
         */
        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++]; //把两个字符串(char数组)中的内容挨个赋值给c1,c2
            if (c1 == c2) {     //然后拿c1,c2挨个比较
                continue;       //如果相等,就结束本次循环,继续下一次,否则往下找执行条件
            }
            if (ignoreCase) {   //传进来的boolen类型的形参,为true时才执行这段
                // 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 toUpperCase(char ch) 形参cf为要转换的字母
                //返回转换后字符的大写形式,如果有的话;否则返回字符本身。
                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
                // 因为Georgian alphabet有奇怪的大小写规则转换。
                // conversion.  So we need to make one last check before
                // 所以我们需要做最后一次检查
                // exiting.
             
                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                    continue;
                }
            }
            return false;
        }
        return true;
    }

因为()里面的通常是形参,当传来的为null的时候,会出现异常,
还有不要直接出现这种字符串,要用变量去接收,或者定义为常量。

9. public String replace(String oldStr,String newStr);将字符串中的oldStr替换成newStr,然后得到一个新字符串

String a = "abcdeabcf42abc";
System.out.println(a.replace("abc", "XXX"));//XXXdeXXXf42XXX

源码:把数组中的oldChar字符换成newChar字符
    public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) { //如果两个字符相同,那么就返回源字符串,不重新new
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */ //避免失败的操作?

            while (++i < len) {
                if (val[i] == oldChar) {  //找到这个字符的位置
                    break;
                }
            }
            if (i < len) {
                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;
    }




当要更换的是字符串的时候,调用的是以下方法:CharSequence字符序列,但该就是字符串了吧...
    public String replace(CharSequence target, CharSequence replacement) {
        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
    }
原谅我没有看懂这个玩意.....

10.public String substring(int beginIndex, int endIndex),将字符串中第beginIndex(包含)到endIndex(不包含)截取                         public String substring(int beginIndex), 将字符串中第beginIndex(包含)到最后截取

String a = "abcdeabcf42abc";
System.out.println(a.substring(5, 10));//abcf4
System.out.println(a.substring(5));//abcf42abc

为什么不包含endIndex?
当不写的时候,默认截取到数组的最后,而数组是从0开始计起,
所以截取到最后即为lengt-1个数,所以输入10即截取到10-1=9个。
多想想吧


源码:
    public String substring(int beginIndex) {
        if (beginIndex < 0) {   //开始位置小于0,抛出异常
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;//被截取后新数组的长度
        if (subLen < 0) {      //被截取后新的数组长度小于0就抛出异常
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }

    /*
     *如果截取的开始位置为0,那么直接返回这个字符串(没有new一个)
     *否则,便会调用String的带三个参数的构造方法,从新new一个String保存并返回该结果
     */


    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);
        }
        //返回该数组的条件多了一个,即截取的是最后一个位置,即endIndex == value.length
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

11.public String trim(),去除前面和尾部的空格,(中间的空格去除不了哦)

String password="123456 ";//多了个空格
System.out.println("123456".equals(password));//false
String b=password.trim();
System.out.println("123456".equals(b));//true

源码:
    public String trim() {
        int len = value.length;
        int st = 0;
        char[] val = value;    /* avoid getfield opcode */

        while ((st < len) && (val[st] <= ' ')) {
            st++;
        }
        while ((st < len) && (val[len - 1] <= ' ')) {
            len--;
        }
        return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
    }

12. public String concat(String str),将指定字符串连接到此字符串的结尾

String a = "abcdeabcf42abc";
System.out.println(a.concat("555").equals(a));//false
System.out.println(a.concat("").equals(a));//true

如果参数字符串的长度为 0,则返回此 String 对象。

源码:
    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(buf, len); //把str添加到buf数组len位置之后
        return new String(buf, true); //返回一个新字符串
    }

13.public String[] split(String str),拆分(删除)数组中的str字符串,返回的是String数组

String a="123dabd456dccc";
String[] bs=a.split("d");
//split可以根据正则表达式切割
for (int i = 0; i < bs.length; i++) {
	System.out.println(bs[i]);
}


源码:

    public String[] split(String regex) {
        return split(regex, 0);
    }



    public String[] split(String regex, int limit) {
        /* fastpath if the regex is a
         (1)one-char String and this character is not one of the
            RegEx's meta characters ".$|()[{^?*+\\", or
         (2)two-char String and the first char is the backslash and
            the second is not the ascii digit or ascii letter.
         */
        char ch = 0;
        if (((regex.value.length == 1 &&
             ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
             (regex.length() == 2 &&
              regex.charAt(0) == '\\' &&
              (((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
              ((ch-'a')|('z'-ch)) < 0 &&
              ((ch-'A')|('Z'-ch)) < 0)) &&
            (ch < Character.MIN_HIGH_SURROGATE ||
             ch > Character.MAX_LOW_SURROGATE))
        {
            int off = 0;
            int next = 0;
            boolean limited = limit > 0;
            ArrayList<String> list = new ArrayList<>();
            while ((next = indexOf(ch, off)) != -1) {
                if (!limited || list.size() < limit - 1) {
                    list.add(substring(off, next));
                    off = next + 1;
                } else {    // last one
                    //assert (list.size() == limit - 1);
                    list.add(substring(off, value.length));
                    off = value.length;
                    break;
                }
            }
            // If no match was found, return this
            if (off == 0)
                return new String[]{this};

            // Add remaining segment
            if (!limited || list.size() < limit)
                list.add(substring(off, value.length));

            // Construct result
            int resultSize = list.size();
            if (limit == 0) {
                while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
                    resultSize--;
                }
            }
            String[] result = new String[resultSize];
            return list.subList(0, resultSize).toArray(result);
        }
        return Pattern.compile(regex).split(this, limit);
    }

14.public char[] toCharArray(),将此字符串转换为一个新的字符数组。

 

String a="abc";
char[] bs=a.toCharArray();
for (int i = 0; i < bs.length; i++) {
	System.out.println(bs[i]);
}

源码:
    不能使用数组复制,因为类初始化顺序问题
    public char[] toCharArray() {
        // Cannot use Arrays.copyOf because of class initialization order issues
        char result[] = new char[value.length];
        System.arraycopy(value, 0, result, 0, value.length);
        return result;
    }

内容有点长,我也觉得很啰嗦了,怕是很难有兴趣看完,不过这玩意就是这样的....

以上纯属个人理解观点(可能会有理解错的,希望不会把你带往错误的道路),欢迎留言一起讨论!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值