研究一个类之前我们来说说类的构成:
一个类主要分为几个部分:分别是类的定义(类的继承,接口的实现),全局变量方法,属性,内部类等.
第一点: 实现的接口
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; }