1.String
1)String类位于java.lang包中,代表字符串;Java把String类声明为final类,不能有子类;String类对象一旦创建后就不能够修改,其底层其实是由字符数组构成的。
2)常用方法
<1>新建字符串
String str = new String([字符串常量]);
String str = 字符串常量;
<2>构造方法
/*无参构造方法,创建空的字符串对象*/
public String() {
this.value = "".value;
}
/*通过字符串常量创建字符串对象*/
public String(String original) {
this.value = original.value;
/*同时将字符串常量的hash code赋值给字符串对象*/
this.hash = original.hash;
}
/*通过字符数组创建字符串对象*/
public String(char value[]) {
/*由于其底层是数组,只需将字符数组Copy一份至新字符串对象的value值即可*/
this.value = Arrays.copyOf(value, value.length);
}
/*通过字符串数组创建字符串对象,是从字符数组的第offset开始,count个字符创建的*/
public String(char value[], int offset, int count) {
//对参数offset进行合法性判断,不能<0,否则抛异常
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
//对参数count进行合法性判断
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
//count==0,offset<=value.length 则是空字符串
if (offset <= value.length) {
this.value = "".value;
return;
}
}
//如果sffset+count的长度>value.length,也需要抛出异常
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
//使用Arrays的copyOfRange();
this.value = Arrays.copyOfRange(value, offset, offset+count);
}
/*将字节数组按照字节码对应的字符转为字符串*/
public String(byte bytes[]) {
this(bytes, 0, bytes.length);
}
public String(byte bytes[], int offset, int length) {
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(bytes, offset, length);
}
<3>常用方法:
查找:
/*获取字符串长度*/
public int length() {
//返回字符数组长度
return value.length;
}
/*查找指定位置字符,第一个字符下标是0*/
public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}
/*提取子字符串,提取的是从beginIndex到结尾的子字符串*/
public String substring(int beginIndex) {
//对beginIndex进行合法性判断
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
//new 一个String对象,通过String(char value[], int offset, int count)构造方法
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
/*提取子串,获取从beginIndex到endIndex*/
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);
}
获取字符位置:
/*获取字符ch在字符串中的位置(数组下标)*/
public int indexOf(int ch) {
return indexOf(ch, 0);
}
/*从fromIndex位置开始查找,获取字符ch在字符串中的位置(数组下标)*/
public int indexOf(int ch, int fromIndex) {
final int max = value.length;
if (fromIndex < 0) {
fromIndex = 0;
} else if (fromIndex >= max) {
// Note: fromIndex might be near -1>>>1.
return -1;
}
//public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
//判断是否在65536范围内,在范围内直接查找就可以,不在则说明是补充字符码,使用indexOfSupplementary(ch, fromIndex)方法;
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
final char[] value = this.value;
for (int i = fromIndex; i < max; i++) {
if (value[i] == ch) {
return i;
}
}
return -1;
} else {
return indexOfSupplementary(ch, fromIndex);
}
}
获取子字符串位置
/*获取子字符串在字符串中出现的首次位置*/
public int indexOf(String str) {
return indexOf(str, 0);
}
/*从fromIndex开始查找,获取子字符串在字符串中出现的首次位置*/
public int indexOf(String str, int fromIndex) {
return indexOf(value, 0, value.length,
str.value, 0, str.value.length, fromIndex);
}
/*与上边两个方法类似,不过从字符串的末尾往前查询*/
public int lastIndexOf(String str) {
return lastIndexOf(str, value.length);
}
public int lastIndexOf(String str, int fromIndex) {
return lastIndexOf(value, 0, value.length,
str.value, 0, str.value.length, fromIndex);
}
/*source字符串, sourceOffset开始位置, sourceCount字符串长度,target子字符串, targetOffset开始位置, targetCount子字符串长度, fromIndex字符串开始查询的位置*/
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
//参数合法性判断,0<fromIndex<=sourceCount
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
//先查找子字符里的第一个字符在字符串中的位置
char first = target[targetOffset];
//最多查到字符串的倒数targetCount个位置,超出这个位置剩下的就一定不存在子字符串了
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 */
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;
}
比较:
/*比较两个字符串是否相等,比较的是内容*/
public boolean equals(Object anObject) {
//如果是同一对象,一定相等
if (this == anObject) {
return true;
}
//anObject是否是String的一个实例
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;
}
/*忽略大小写比较两个字符串是否相等*/
public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true
: (anotherString != null)
&& (anotherString.value.length == value.length)
&& regionMatches(true, 0, anotherString, 0, value.length);
}
/*两个字符串大小比较,返回值是两个字符串的长度之差或者第一个不相等字符的字符码之差*/
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) {
//,如果是在两个字符串中短者的范围内,返回的事第一个不相等字符的Unicode码之差
return c1 - c2;
}
k++;
}
//返回的是字符串长度之差,其实也就是说其中一个是另一个的子串时候,返回的是长度之差。
return len1 - len2;
}
/*忽略大小写的比较大小*/
public int compareToIgnoreCase(String str) {
//CASE_INSENSITIVE_ORDER.compare(this, str);是String类的一个静态内部类
return CASE_INSENSITIVE_ORDER.compare(this, str);
}
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);
//将字符串循环,然后通过Character的大小写转换,进行比较
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; }
}
拼接:
/*将字符串拼接到已知字符串之后,与+类似*/
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);
//返回的是一个新的字符串对象!
return new String(buf, true);
}
替换:
/*字符替换,返回的是替换后的新字符串*/
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) {
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;
}
/*替换第一次匹配到的字符串*/
public String replaceFirst(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
}
/*字符串替换*/
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
转换:
public String toLowerCase(){...}//返回将当前字符串中所有字符转换成小写后的新串
public String toUpperCase(){...}//返回将当前字符串中所有字符转换成大写后的新串
public static String valueOf(Object obj){...}//基本数据类型转字符串,参数可以是任意字符串类型
其他:
public String[] split(String str){...}//将str作为分隔符进行字符串分解,分解后的字字符串在字符串数组中返回。
public String trim(){...}//截取字符串两头的空格,对于中间的空格不做处理。
public boolean contains(String str)//判断参数s是否被包含在字符串中,并返回一个布尔类型的值
3)字符串常量池
<1>字符串是存储在字符串常量池中的,字符串常量池是位于方法区中的;
<2>字符串在创建时候是先在字符串常量池中查看是否已经有该字符串,如果有就直接引用到该字符串,没有的话就先创建该字符串,然后引用:
String str1 = "ABC";
在字符串常量池中创建"ABC",str直接指向该字符串
String str2 = new String("ABCD");
在字符串常量池中创建"ABCD"对象,然后在堆中新建new String("ABCD")对象,然后str指向该对象
String str3 = new String("A"+"B");
在字符串常量池中新建了"A","B","AB"三个对象,然后再堆中新建了一个new String("AB")对象,然后str3指向该对象
String str4 = new String("ABCDE")+"ABCDE";//
在字符串常量池中创建"ABCDE"对象,然后新建new String("ABCDE")对象,然后在字符串常量池中创建"ABCDEABCDE"对象,然后str4指向该常量池中的字符串
<3>使用字符串常量池的好处:字符串是作为最基础的引用数据类型,使用率是极高的,大量频繁的创建销毁对象,对于性能有很大的影响,因此使用字符串常量池,使得字符串常量池中的字符串不会被垃圾回收机制回收,在不会影响其他对象对字符串的引用;并且将字符串放进字符串常量池后,是不会再改变该字符串的,可以不用担心数据共享时候的冲突。