深耕JavaSe - String类源码解析

深耕JavaSe - String类源码解析,第1张

深耕JavaSe - String类源码解析

文章目录
    • 1. String类的定义
    • 2. 字段属性
    • 3. 常用构造方法
    • 4. 其他常用方法

1. String类的定义
public final class String implements Serializable, Comparable, CharSequence

根据String类的定义,可以得出:

1、String类是被final关键字修饰的类:

① final修饰的类不能被继承,final类中的成员变量可以根据需要设为final,但final类中的所有成员方法都会被隐式地指定为final方法。

② 当final关键字用来修饰一个方法的时候,这个方法就是最终方法,不能够被覆盖重写。

2、String类实现了java.io.Serializable接口,可以实现序列化:

① 序列化是指把对象转换为字节序列的过程,我们称之为对象的序列化,就是把内存中的这些对象变成一连串的字节(bytes)描述的过程。

② 反序列化则相反,就是把持久化的字节文件数据恢复为对象的过程。

3、String类实现了Comparable,可以用于比较大小:

// 这个接口只有一个compareTo(T 0)方法,用于对两个实例化对象比较大小。
public interface Comparable {
    int compareTo(T var1);
}

2. 字段属性
private final char value[];


private int hash; // Default to 0

① 被final修饰的变量一旦被赋初始值,final变量的值以后将不会被改变。

② value[]是存储String的内容的,即当使用String str = "abc";的时候,本质上,"abc"是存储在一个char类型的数组中的。

③ hash是String实例化的hashcode的一个缓存。因为String经常被用于比较,比如在HashMap中。如果每次进行比较都重新计算hashcode的值的话,那无疑是比较麻烦的,而保存一个hashcode的缓存无疑能优化这样的 *** 作。


3. 常用构造方法

1、 构造方法:String()

// 初始化一个新创建的String 对象,使其代表空字符序列。请注意,此构造函数的使用是不必要,因为字符串是不可变的。
public String() {
    this.value = new char[0];
}

2、 构造方法:String(char value[])

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

3、构造方法:String(char value[], int offset, int count)

public String(char value[], int offset, int count) {
    // 参数校验
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count < 0) {
        throw new StringIndexOutOfBoundsException(count);
    }
    if (offset > value.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }
    // 数组的拷贝
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}
public static char[] copyOfRange(char[] original, int from, int to) {
    int newLength = to - from;
    if (newLength < 0)
        throw new IllegalArgumentException(from + " > " + to);
    char[] copy = new char[newLength];
    System.arraycopy(original, from, copy, 0,
                     Math.min(original.length - from, newLength));
    return copy;
}

4、构造方法:String(byte bytes[], int offset, int length)

public String(byte bytes[], int offset, int length) {
    checkBounds(bytes, offset, length);
    this.value = StringCoding.decode(bytes, offset, length);
}
private static void checkBounds(byte[] bytes, int offset, int length) {
    if (length < 0)
        throw new StringIndexOutOfBoundsException(length);
    if (offset < 0)
        throw new StringIndexOutOfBoundsException(offset);
    if (offset > bytes.length - length)
        throw new StringIndexOutOfBoundsException(offset + length);
}

5、构造方法:String(byte bytes[])

public String(byte bytes[]) {
    this(bytes, 0, bytes.length);
}

6 、构造方法:String(byte bytes[], Charset charset)

public String(byte bytes[], Charset charset) {
    this(bytes, 0, bytes.length, charset);
}

7、构造方法:String(byte bytes[], int offset, int length, Charset charset)

public String(byte bytes[], int offset, int length, Charset charset) {
    if (charset == null)
        throw new NullPointerException("charset");
    checkBounds(bytes, offset, length);
    this.value =  StringCoding.decode(charset, bytes, offset, length);
}

8、构造方法:String(StringBuffer buffer)

public String(StringBuffer buffer) {
    // 加了synchronized,说明是线程安全的,同一时间只有一个线程可以 *** 作
    synchronized(buffer) {
        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}
public static char[] copyOf(char[] original, int newLength) {
    char[] copy = new char[newLength];
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

9、构造方法:String(StringBuilder builder)

public String(StringBuilder builder) {
    this.value = Arrays.copyOf(builder.getValue(), builder.length());
}

String支持多种构造方法,包括接收String,char[],byte[],StringBuffer,StringBuilder等多种参数类型的初始化方法。但本质上,其实就是将接收到的参数传递给全局变量value[]。


4. 其他常用方法

1、int length()

// 存放字符串中的字符
private final char value[];

// 返回字符串的长度
public int length() {
    return value.length;
}

2、boolean isEmpty()

// 存放字符串中的字符
private final char value[];

// 判断字符串是否为空,就是判断value的长度是否为空
public boolean isEmpty() {
    return value.length == 0;
}

3、char charAt(int index)

// 存放字符中指定索引处的字符
private final char value[];

// 返回指定索引处的 char 值
public char charAt(int index) {
    // 参数校验
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}

4、getChars(char dst[], int dstBegin

// 从 dstBegin 开始,将此字符串中的字符复制到字符数组 dst 中, 此方法不执行任何范围检查。
void getChars(char dst[], int dstBegin) {
    System.arraycopy(value, 0, dst, dstBegin, value.length);
}
public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);

5、void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin)

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
    if (srcBegin < 0) {
        throw new StringIndexOutOfBoundsException(srcBegin);
    }
    if (srcEnd > value.length) {
        throw new StringIndexOutOfBoundsException(srcEnd);
    }
    if (srcBegin > srcEnd) {
        throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
    }
    System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

6、byte[] getBytes(String charsetName)

// 使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
    if (charsetName == null) throw new NullPointerException();
    return StringCoding.encode(charsetName, value, 0, value.length);
}

7、byte[] getBytes(Charset charset)

// 使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。 
public byte[] getBytes(Charset charset) {
    if (charset == null) throw new NullPointerException();
    return StringCoding.encode(charset, value, 0, value.length);
}

8、 byte[] getBytes()

// 使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 
public byte[] getBytes() {
    return StringCoding.encode(value, 0, value.length);
}

9、equals(Object anObject)

// 判断两个字符串是否相等
public boolean equals(Object anObject) {
    // 比较对象的内存地址,当两个对象的内存地址相同时,说明是同一个对象,因此返回true
    if (this == anObject) {
        return true;
    }
    //  在 Java 中可以使用 instanceof 关键字判断一个对象是否为一个类(或接口、抽象类、父类)的实例
    //  anObject对象是String类的实例或者子类实例时,则返回true,一般在强制转换之前判断
    if (anObject instanceof String) {
        // 强制转换为String类型
        String anotherString = (String)anObject;
        int n = value.length;
        // 判断当前字符串和传入字符串的长度是否相等,不相等直接返回false
        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;
}

10、boolean equalsIgnoreCase(String anotherString)

// 判断两个字符串是否相等,忽略字符串的大小写
public boolean equalsIgnoreCase(String anotherString) {
    // 1、判断两个字符串对象的内存地址是否相同,如果相同直接返回true
    // 2、否则继续判断:
    //    1、字符串不能为null
    //    2、两个字符串的长度相同
    //    3、将两个字符串中的字符转换为大写,小写后再比较两个字符串的字符串是否相等
    return (this == anotherString) ? true
            : (anotherString != null)
            && (anotherString.value.length == value.length)
            && regionMatches(true, 0, anotherString, 0, value.length);
}
public boolean regionMatches(boolean ignoreCase, int toffset,
                             String other, int ooffset, int len) {
    // 此字符串对应的字符数组
    char ta[] = value;
    // 此字符串的起始指针
    int to = toffset;
    // 参数字符串的起始指针
    char pa[] = other.value;
    // 参数字符串对应的字符数组
    int po = ooffset;
    // 参数校验
    if ((ooffset < 0) || (toffset < 0)
        || (toffset > (long)value.length - len)
        || (ooffset > (long)other.value.length - len)) {
        return false;
    }
    // 比较字符数组中的每个字符是否相同
    while (len-- > 0) {
        // 获取此字符指针指向的字符
        char c1 = ta[to++];
        // 获取参数字符串指针指向的字符
        char c2 = pa[po++];
        // 判断两个字符是否相同,如果相同,则比较扫描继续
        if (c1 == c2) {
            continue;
        }
        if (ignoreCase) {
            // 如果字符不匹配但大小写可能会被忽略,尝试将两个字符都转换为大写, 如果结果匹配,那么比较扫描应该继续
            char u1 = Character.toUpperCase(c1);
            char u2 = Character.toUpperCase(c2);
            if (u1 == u2) {
                continue;
            }
            //不幸的是,Georgian alphabet不能正常转换为大写字母,Georgian alphabet对大小写转换有奇怪的规则。 所以我们需要在退出前做最后一次检查。
            if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                continue;
            }
        }
        return false;
    }
    return true;
}

11、int compareTo(String anotherString)

// 按字典顺序比较两个字符串。该方法实现了Comparable接口的方法
// 按字典顺序比较两个字符串。该比较基于字符串中各个字符的 Unicode 值。
// 按字典顺序将此 String 对象表示的字符序列与参数字符串所表示的字符序列进行比较。
// 如果按字典顺序此 String 对象位于参数字符串之前,则比较结果为一个负整数。
// 如果按字典顺序此 String 对象位于参数字符串之后,则比较结果为一个正整数。
// 如果这两个字符串相等,则结果为 0;
// compareTo 只在方法 equals(Object) 返回 true 时才返回 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;
}

12、boolean startsWith(String prefix, int toffset)

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;
    // 参数校验
    if ((toffset < 0) || (toffset > value.length - pc)) {
        return false;
    }
    // 判断每个字符是否相同
    while (--pc >= 0) {
        if (ta[to++] != pa[po++]) {
            return false;
        }
    }
    return true;
}

13、boolean startsWith(String prefix)

public boolean startsWith(String prefix) {
    // 索引从0开始
    return startsWith(prefix, 0);
}

14、boolean endsWith(String suffix)

public boolean endsWith(String suffix) {
    return startsWith(suffix, value.length - suffix.value.length);
}

15、int 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;
}

16、int indexOf(int ch, int fromIndex)

public int indexOf(int ch, int fromIndex) {
    final int max = value.length;
    // 参数校验,如果索引小于0,设置为0,
    if (fromIndex < 0) {
        fromIndex = 0;
    } else if (fromIndex >= max) {
        // 如果索引大于字符串字符的长度,返回-1,代表此字符串中没有这样的字符。
        return -1;
    }
    if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
        // 当前字符串对应的字符数组
        final char[] value = this.value;
        // 从从指定的索引开始遍历字符数组,判断字符数组中的字符是否等于指定字符,如果找到,直接返回索引
        for (int i = fromIndex; i < max; i++) {
            if (value[i] == ch) {
                // 此时返回的就是字符串中第一次出现指定字符的索引
                return i;
            }
        }
        return -1;
    } else {
        // 使用补充字符处理(罕见)对 indexOf 的调用。
        return indexOfSupplementary(ch, fromIndex);
    }
}

17、int indexOf(int ch)

public int indexOf(int ch) {
    return indexOf(ch, 0);
}

18、int lastIndexOf(int ch, int fromIndex)

public int lastIndexOf(int ch, int fromIndex) {
    if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
        // 当前字符串对应的字符数组
        final char[] value = this.value;
        // 没有做参数处理,当参数fromIndex的值大于value.length - 1时,取 i=value.length - 1
        int i = Math.min(fromIndex, value.length - 1);
        // 遍历整个字符串
        for (; i >= 0; i--) {
            // 从字符产的最后一个字符往前遍历,判断遍历到的字符与指定字符是否相同 
            if (value[i] == ch) {
                // 此时返回的是字符串中最后一次出现指定字符的索引
                return i;
            }
        }
        // 如果此字符串中 fromIndex 或之前的位置没有这样的字符出现,则返回 -1。
        return -1;
    } else {
        return lastIndexOfSupplementary(ch, fromIndex);
    }
}

19、int lastIndexOf(int ch)

public int lastIndexOf(int ch) {
    return lastIndexOf(ch, value.length - 1);
}

20、String substring(int 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);
    }
    // 如果beginIndex==0,直接返回字符串,否则重新创建一个子字符串
    // 因为字符串一旦创建后就是不变的
    return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

21、String substring(int beginIndex, int 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);
}

22、String concat(String str)

public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    // 创建一个长度为len+otherLen的数组,然后将String对应的字符数组value拷贝到该数组中
    char buf[] = Arrays.copyOf(value, len + otherLen);
    // 将字符从此字符串复制到目标字符数组,目标数组中的起始拷贝位置为len
    str.getChars(buf, len);
    // 创建一个新的字符串
    return new String(buf, true);
}
void getChars(char dst[], int dstBegin) {
    System.arraycopy(value, 0, dst, dstBegin, value.length);
}
public static char[] copyOf(char[] original, int newLength) {
    //创建一个长度为newLength的目标数组
    char[] copy = new char[newLength];
    // 将原数组original中的字符拷贝到目标数组中
    System.arraycopy(original, 0, copy, 0,
            Math.min(original.length, newLength));
    return copy;
}

23、String replace(char oldChar, char newChar)

public String replace(char oldChar, char newChar) {
    // 如果旧字符和新字符不相等,就执行替换
    if (oldChar != newChar) {
        int len = value.length;
        int i = -1;
        char[] val = value; 

        // 从字符串中找到当前要替换字符的索引
        while (++i < len) {
            if (val[i] == oldChar) {
                break;
            }
        }
        if (i < len) {
            // 创建一个长度为len字符数组
            char buf[] = new char[len];
            // 将val字符数组下标从0到i(不包括i)之间的字符复制到新的字符数组buf中
            // 即将0~i之间的字符复制到新字符数组buf中
            for (int j = 0; j < i; j++) {
                buf[j] = val[j];
            }
            // 取出val数组中的每一个字符, 判断是否是oldChar,如果是就将其替换为newChar放进数组buf中
            // 如果不是oldChar,就直接把这个字符放进buf中
            while (i < len) {
                char c = val[i];
                buf[i] = (c == oldChar) ? newChar : c;
                i++;
            }
            // 创建一个字符串,即将buf数组赋值给String的value数组
           return new String(buf, true);
        }
    }
    return this;
}

24、String replaceAll(String regex, String replacement)

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

25、String trim()

public String trim() {
    //
    int len = value.length;
    int st = 0;
    char[] val = value;    

    while ((st < len) && (val[st] <= ' ')) {
        st++;
    }
    while ((st < len) && (val[len - 1] <= ' ')) {
        len--;
    }
    return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

26、char[] toCharArray()

public char[] toCharArray() {
    // 创建一个长度等于value.length的字符数组
    char result[] = new char[value.length];
    // 将value数组拷贝到result数组中
    System.arraycopy(value, 0, result, 0, value.length);
    return result;
}

27、String valueOf(char c)

public static String valueOf(char c) {
    char data[] = {c};
    return new String(data, true);
}

28、String valueOf(boolean b)

// 返回boolean参数的字符串表示形式。 
public static String valueOf(boolean b) {
    return b ? "true" : "false";
}

29、String valueOf(int i)

// 返回int参数的字符串表示形式。
public static String valueOf(int i) {
    return Integer.toString(i);
}

30、String valueOf(long l)

// 返回long参数的字符串表示形式。
public static String valueOf(long l) {
    return Long.toString(l);
}

31、String valueOf(float f)

public static String valueOf(float f) {
    return Float.toString(f);
}

32、String valueOf(double d)

public static String valueOf(double d) {
    return Double.toString(d);
}

33、String intern()

public native String intern();

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5660541.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存