研究一个类之前我们来说说类的构成:
一个类主要分为几个部分:分别是类的定义(类的继承,接口的实现),全局变量方法,属性,内部类等.
第一点: 实现的接口
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence
Sting 是一个由final 修饰的常量类,在java中由final修饰的常量类是不可以任何类被继承的,同时一个String对象被创建, 包含在这个对象中的字符序列是不可改变的,实现Serializable 序列化接口,Comparable用于对两个实例化对象比较大小,CharSequence一个只读的字符序列。
//序列化接口
public interface Serializable {
}
//比较两个实例化对象大小的接口
public interface Comparable<T> {
public int compareTo(T o);
}
//一个只读的字符序列
public interface CharSequence {
int length();
char charAt(int index);
CharSequence subSequence(int start, int end);
public String toString();
public default IntStream chars() {
class CharIterator implements PrimitiveIterator.OfInt {
int cur = 0;
public boolean hasNext() {
return cur < length();
}
public int nextInt() {
if (hasNext()) {
return charAt(cur++);
} else {
throw new NoSuchElementException();
}
}
@Override
public void forEachRemaining(IntConsumer block) {
for (; cur < length(); cur++) {
block.accept(charAt(cur));
}
}
}
return StreamSupport.intStream(() ->
Spliterators.spliterator(
new CharIterator(),
length(),
Spliterator.ORDERED),
Spliterator.SUBSIZED | Spliterator.SIZED | Spliterator.ORDERED,
false);
}
public default IntStream codePoints() {
class CodePointIterator implements PrimitiveIterator.OfInt {
int cur = 0;
@Override
public void forEachRemaining(IntConsumer block) {
final int length = length();
int i = cur;
try {
while (i < length) {
char c1 = charAt(i++);
if (!Character.isHighSurrogate(c1) || i >= length) {
block.accept(c1);
} else {
char c2 = charAt(i);
if (Character.isLowSurrogate(c2)) {
i++;
block.accept(Character.toCodePoint(c1, c2));
} else {
block.accept(c1);
}
}
}
} finally {
cur = i;
}
}
public boolean hasNext() {
return cur < length();
}
public int nextInt() {
final int length = length();
if (cur >= length) {
throw new NoSuchElementException();
}
char c1 = charAt(cur++);
if (Character.isHighSurrogate(c1) && cur < length) {
char c2 = charAt(cur);
if (Character.isLowSurrogate(c2)) {
cur++;
return Character.toCodePoint(c1, c2);
}
}
return c1;
}
}
return StreamSupport.intStream(() ->
Spliterators.spliteratorUnknownSize(
new CodePointIterator(),
Spliterator.ORDERED),
Spliterator.ORDERED,
false);
}
}
第二点:属性
/** The value is used for character storage. */ 用来存储字符窜
private final char value[];
/** Cache the hash code for the string */缓存字符串的哈希码
private int hash; // Default to 0
可以看到,value[]是存储String的内容的,即当使用String str = "abc";的时候,本质上,"abc"是存储在一个char类型的数组中的。
而hash是String实例化的hashcode的一个缓存。因为String经常被用于比较,比如在HashMap中。如果每次进行比较都重新计算hashcode的值的话,那无疑是比较麻烦的,而保存一个hashcode的缓存无疑能优化这样的操作。
第三点:构造方法

第四点:常用的方法
//返回字符窜的长度
public int length() {
return value.length; } //判断字符窜是否为空 public boolean isEmpty() { return value.length == 0; } //返回指定索引下的字符(一个字符窜实际上是由一个字符数组组成) public char charAt(int index) {
//索引越界抛出异常 if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return value[index]; }
Comparable 接口的方法,比较两个字符窜对象的大小
//这个按字母顺序比较两个字符串,是基于字符串中每个字符的 Unicode 值。当两个字符串某个位置的字符不同时,返回的是这一位置的字符 Unicode 值之差,当两个字符串都相同时,返回两个字符串长度之差
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; }
concat 主要拼接字符窜操作,如果拼接的字符窜为空,返回当前当前子字符窜,不为空则在尾部拼接新的字符窜(长度为原字符串和要拼接的字符串之和)
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);
}
int indexOf(String str) :返回第一次出现的指定子字符串在此字符串中的索引。
public int indexOf(String str) {
return indexOf(str, 0);
}
int indexOf(String str, int startIndex):从指定的索引处开始,返回第一次出现的指定子字符串在此字符串中的索引。
public int indexOf(String str, int fromIndex) {
return indexOf(value, 0, value.length,
str.value, 0, str.value.length, fromIndex);
}
int lastIndexOf(String str) :返回在此字符串中最右边出现的指定子字符串的索引。
public int lastIndexOf(String str) {
return lastIndexOf(str, value.length);
}
int lastIndexOf(String str, int startIndex) :从指定的索引处开始向后搜索,返回在此字符串中最后一次出现的指定子字符串的索引。
public int lastIndexOf(String str, int fromIndex) {
return lastIndexOf(value, 0, value.length,
str.value, 0, str.value.length, fromIndex);
}
indexOf(int ch, int fromIndex),split(String regex, int limit)(???????)
replace(char oldChar, char newChar) :将原字符串中所有的oldChar字符都替换成newChar字符,返回一个新的字符串。
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
String replaceAll(String regex, String replacement):将匹配正则表达式regex的匹配项都替换成replacement字符串,返回一个新的字符串。
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
substring(int beginIndex) 返回一个从索引 beginIndex 开始一直到结尾的子字符串。
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
equals(Object anObject)就是比较的是组成字符串的每一个字符是否相同,如果都相同则返回true,否则返回false
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;
}
hashCode()
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}