JAVA源码学习(一)——String类

一、String类的不可变性

源码:

public final class String//final修饰类,不可继承
private final char value[];//String类实际返回值为final修饰的char数组,其对象内容

     1、测试数组char数组能否代替字符串

 public static void main(String[] args) {
        String str = "abc";
        char[] ch = {'a','b','c'};
        System.out.println(str);
        System.out.println(ch);
    }

     结果:可替代

abc
abc

    2、测试String类是否可变

 public static void main(String[] args) {
        String str = "abc";
        String t1 = str;
        str = "ab";
        String t2 =str;
        //假如String可变,t1=t2,反之,t1!=t2
        System.out.println(t1==t2);
    }
 public static void main(String[] args) {
        StringBuilder str = new StringBuilder("abc");
        StringBuilder t1 = str;
        StringBuilder t2 =str.append("d");
        //假如String可变,t1=t2,反之,t1!=t2
        System.out.println(t1==t2);
    }

    结果:不可变

false
true

二、String类常用构造

源码:

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

    1、为何采用Arrays.copyof而非直接用this.value=value

        传递的value为可变对象,将this.value指向它时,则this.value失去不可变性,而Arrays.copyof采用浅复制,保留了this.value的不可变性

    2、源码复制过来一堆错?

        。。。。源码中很多东西,你是没有使用权限的

三、String类常用方法

源码:

    1、length()获取字符串长度

//其实就是获取char数组元素个数
public int length() {
        return value.length;
    }

    2、isEmpty()判断是否为空

//假如字符串为null,则无法使用
public boolean isEmpty() {
        return value.length == 0;
    }

    3、charAt(int i)获取指定位置字符

//返回字符数组指定元素
public char charAt(int index) {
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

    4、equals(Object o )比较是否与指定对象内容相同

//如果是字符串,则挨个比较字符数组内容是否都相同
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) {
                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;
    }

 *equalsIgnoreCase(String str)忽略大小写比较

 //这里不是很明白,为何要比较两次,全大写或全小写,在我看都能实现目的
 if (ignoreCase) {
                char u1 = Character.toUpperCase(c1);
                char u2 = Character.toUpperCase(c2);
                if (u1 == u2) {
                    continue;
                }       
                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                    continue;
                }
            }

    5、compareTo(String s)按字典顺序比较字符串

//长度不一样,返回长度差,字符不一样,返回字符顺序差,完全一致,返回0
 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;
    }

    6、startsWith(String s,int i) 判断字符是否从指定位置以指定字符串开始

public boolean startsWith(String prefix, int toffset) {
        char ta[] = value;
        int to = toffset;
        char pa[] = prefix.value;
        int po = 0;
        int pc = prefix.value.length;
        // Note: toffset might be near -1>>>1.
        if ((toffset < 0) || (toffset > value.length - pc)) {
            return false;
        }
        while (--pc >= 0) {
            if (ta[to++] != pa[po++]) {
                return false;
            }
        }
        return true;
    }

    7、subString(int from,int end)按指定位置截取字符串

//其实就是按位复制字符数组
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);
    }

    8、replace(char old,char new)将字符串中全部old字符替换为new

public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */
//如果不存在想被替换字符,则 i =len
            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;
    }

    9、contains(String str)字符串中是否还有str子字符串

 //借用indexOf,如果存在则得到正数
public boolean contains(CharSequence s) {
        return indexOf(s.toString()) > -1;
    }

   10、matches(String regex)字符串是否满足正则匹配

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

   11、replaceAll(String regex,String ele)按正则替换

public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }

  12、split(String regex,int limit)按正则拆分字符串,获取指定个数的字符串数组

public String[] split(String regex, int limit) {
        
        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 list = new ArrayList<>();
            while ((next = indexOf(ch, off)) != -1) {
//获取未到limit个数,操作继续
                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);
    }

    13、toCharArray()将字符串还原为字符数组

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;
    }

    14、valueOf(Object o)

//如果字符数组或字符则用构造方法,如果是布尔类型,则返回true or false,如果是其他基本数据类型则用包装类的toString,
 public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }
public static String valueOf(char c) {
        char data[] = {c};
        return new String(data, true);
    }
public static String valueOf(int i) {
        return Integer.toString(i);
    }
public static String valueOf(boolean b) {
        return b ? "true" : "false";
    }

    14、format(String format ,Object...params)格式化字符串

 public static String format(String format, Object... args) {
        return new Formatter().format(format, args).toString();
    }

四、正则表达式    

字符

c                                 字符c

\unnnn, \xnn,\0n, \0nn, \0nnn          带有十六或八进制值的代码单元

\0n                               八进制0n代表的字符(0<=n<=7)

\0nn                              八进制0nn代表的字符(0<=n<=7)

\0mnn                             八进制0mnn代表的字符(0<=m<=3,0<=n<=7)

\xnn                              十六进制 0xnn所代表的字符

\uhhhh                            十六进制 0xhhhh所代表的字符

\t, \n, \r, \f,\a, \e控制字符,依次是制表符,换行符,回车符,换页符,报警符和转义符

\cc                               控制字符中出现的相应字符c

字符类

[C1C2. . .] C1、C2……中的任何字符。Ci可以是字符,字符范围(C1-C2)或者字符类。

[^. . .]                            字符类的补集

[ . . .&& . . .]                       两个字符类的交集

预定义字符类

.    除行终止符外的任何字符(如果DOTALL标志置位,则表示任何字符)

\d                                                   数字[0-9]

\D                               非数字[^0-9]

\s                                空白字符[\t\n\r\f\x0B]

\S                                非空白字符

\w                               单词字符[a-zA-Z0-9_]

\W                               非单词字符

\p{name}                          一个指定的字符类,见表12-9

\P{name}                          指定字符类的补集

边界匹配符

^ $       输入的开头和结尾(在多行模式(multilinemode)下是行的开头和结尾)

\b                                单词边界

\B                                非单词边界

\A                                输入的开头

\z                                输入的结尾

\Z 除最后行终止符之外的输入结尾

\G                               上个匹配的结尾

量词

X?                               可选的X(即X可能出现,也可能不出现)

X*                               X,可以重复0次或多次

X+                                             X,可以重复1次或多次

X{n} X{n,}X{n,m}                 X重复n次,至少重复n次,重复n到m次

量词后缀(表达式所有量词都要加)

?                                 设默认(贪婪)匹配为reluctant(勉强)匹配

+                                设默认(贪婪)匹配为possessive(强制)匹配

贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。如上面使用模式p匹配字符串str,结果就是匹配到:abcaxc(ab*c)。

非贪婪匹配:就是匹配到结果就好,就少的匹配字符。如上面使用模式p匹配字符串str,结果就是匹配到:abc(ab*c)。


。z~~z~~  深夜1.11完稿。。。。。。。睡觉走起。。。









    


你可能感兴趣的:(java源码分析)