java源码阅读系列-String

来源:互联网 发布:java list 排序 编辑:程序博客网 时间:2024/05/16 05:23

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<String>, 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,是就继续往下比较,首先比较长度,然后在每一个去比较。

这次源码阅读就到这里。


原创粉丝点击