一、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<String> 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完稿。。。。。。。睡觉走起。。。