java源码阅读系列-String

String源码

惯例,膜拜Lee Boynton大神

先来看看官方注释对String的解释

 * Strings are constant; their values cannot be changed after they
 * are created. String buffers support mutable strings.
 * Because String objects are immutable they can be shared.
String是常量,它们的值被创建后不能变化,String缓存区是可变的String,因为String类的不可变字符串对象是可以被共享的。


下面开始贴源码。
public final class String
    implements java.io.Serializable, Comparable, CharSequence { ... }
没有继承其他的父类。
实现了Serializable接口,可以序列化。
实现了Comparable接口,主要是用来排序。
实现了CharSequence接口,这个就是一个字符序列,说明String就是字符数据组成的。
/** 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是char的数组,可以知道String就是有char数组来存储的,看到没有,是final的,是不可变的。
hash变量,默认是0。

构造方法

1.无参的构造方法

public String() {
        this.value = "".value;}

2.有参的构造方法(参数为String类)

public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

3.有参的构造方法(用字符数组来构造)

第一种:

 public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }
这里用了Arrays.coprOf方法.

第二种

 public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
offset表示开始位置,count表示截取的长度。

4.用整形的数组来构造

public String(int[] codePoints, int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= codePoints.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > codePoints.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }

        final int end = offset + count;

        // Pass 1: Compute precise size of char[]
        int n = count;
        for (int i = offset; i < end; i++) {
            int c = codePoints[i];
            if (Character.isBmpCodePoint(c))
                continue;
            else if (Character.isValidCodePoint(c))
                n++;
            else throw new IllegalArgumentException(Integer.toString(c));
        }

        // Pass 2: Allocate and fill in char[]
        final char[] v = new char[n];

        for (int i = offset, j = 0; i < end; i++, j++) {
            int c = codePoints[i];
            if (Character.isBmpCodePoint(c))
                v[j] = (char)c;
            else
                Character.toSurrogates(c, v, j++);
        }

        this.value = v;
    }

5.用字符数组构造

第一种

public String(byte bytes[], Charset charset) {
        this(bytes, 0, bytes.length, charset);
    }
该构造方法制定用charset来解码制定的bytes[],为什么要使用charset来制定解码?因为在byte和String这种类型相互转换的时候,会出现乱码,所以我们要制定解码的格式.

第二种

public String(byte bytes[], int offset, int length, String charsetName)
            throws UnsupportedEncodingException {
        if (charsetName == null)
            throw new NullPointerException("charsetName");
        checkBounds(bytes, offset, length);
        this.value = StringCoding.decode(charsetName, bytes, offset, length);
    }
这个是另一种解码方法,使用decode方法.

6.使用StringBuffer和StringBuilder来构造一个String

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

这两个方法很少用,因为我们有toString方法啊.
StringBuffer的toString方法
public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }
StringBuilder的toString方法
public String toString() {
        // Create a copy, don't share the array
        return new String(value, 0, count);
    }

好了,构造方法就这么多.其实不是的,还有一些不建议使用的,就是你在使用的时候会有横线提示你不建议使用.这里就不贴出不来了.你需要知道这列就足够了.


其他方法

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];
    }
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;
    }
转化为字符数组
public String trim() {
        int len = value.length;
        int st = 0;
        char[] val = value;    /* avoid getfield opcode */

        while ((st < len) && (val[st] <= ' ')) {
            st++;
        }
        while ((st < len) && (val[len - 1] <= ' ')) {
            len--;
        }
        return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
    }
去掉两端空格
public String toUpperCase(Locale locale)//大写
public String toLowerCase(Locale locale)//小写

equals方法

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;
    }

执行逻辑:先判断this == anObject,是就直接返回true;之后判断anObject是不是String类型的,不是直接返回false,是就继续往下比较,首先比较长度,然后在每一个去比较。

这次源码阅读就到这里。


你可能感兴趣的:(源码阅读)