天天看点

源码学习:String源码分析String源码学习

String源码学习

目录

String源码学习

string类的定义

string类的变量

string类的构造方法

length方法

isEmpty方法

charAt方法

equals方法

equalsIgnoreCase方法

compareTo方法

startWith方法

string类的定义

    public final class String

        implements java.io.Serializable, Comparable<String>, CharSequence {

(1)string类是被final修饰的,说明该类不能被继承。

(2)string类被设计成final类型:

    1)安全。string类被设计成final类型,表示不可被继承,不可继承就不会被修改,从而避免了因为继承而引起的安全隐患。

    2)效率。string类在程序中出现的频率比较高,如果是为了降低安全隐患,在它每次出现时都用final来修饰,这样会降低程序的执行效率,所以将其设置为final类型,从而提高了效率。

(3)string类实现了serializable(可序列化)、comparable(用到compareto方法)、charsequence(charsequence与string都可以用来定义字符串,charsequence的值是可读可写序列,string的值是只读序列)三个接口。

string类的变量

//用于存储字符的字符数组,值不可更改

    private final char value[];

//该字符串的hash code,默认值为0

    private int hash; // Default to 0

private static final long serialVersionUID = -6849794470754667710L;

private static final ObjectStreamField[] serialPersistentFields =

        new ObjectStreamField[0];

(1)string类是char[]数组存储的数据,数组用final修饰,其为常量,只能被赋值一次。

string类的构造方法

(1)无参数的构造方法。

public String() {

    this.value = "".value;

}

(2)参数为string类型的构造方法。

public String(String original) {

        this.value = original.value;

        this.hash = original.hash;

}

(3)参数为char数组的构造方法

public String(char value[]) {

    this.value = Arrays.copyOf(value, value.length);

}

(4)参数为char数组的构造方法

从char数组的offset位置开始,截取count个字符,赋值给string的value。

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

}

length方法

public int length() {

        return value.length;

}

length方法返回value数组的长度。

isEmpty方法

public boolean isEmpty() {

        return value.length == 0;

}

isEmpty方法判断value数组长度是否为0。

charAt方法

public char charAt(int index) {

        if ((index < 0) || (index >= value.length)) {

            throw new StringIndexOutOfBoundsException(index);

        }

        return value[index];

}

charAt方法返回value数组中下标为index的元素。

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;

}

string类的equals方法:

(1)先是判断两个字符串是否是对同一个对象的引用,即两者在内存中的地址是否相同。

(2)判断是否属于string类型,不是的话,则返回false。

(3)判断两个字符串的长度是否相等,不相等返回false。

(4)逐次判断两个字符串中的单个字符是否相等,不相等返回false,否则继续。

equalsIgnoreCase方法

public boolean equalsIgnoreCase(String anotherString) {

        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;

        // Note: toffset, ooffset, or len might be near -1>>>1.

        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) {

                // If characters don't match but case may be ignored,

                // try converting both characters to uppercase.

                // If the results match, then the comparison scan should

                // continue.

                char u1 = Character.toUpperCase(c1);

                char u2 = Character.toUpperCase(c2);

                if (u1 == u2) {

                    continue;

                }

                // Unfortunately, conversion to uppercase does not work properly

                // for the Georgian alphabet, which has strange rules about case

                // conversion.  So we need to make one last check before

                // exiting.

                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {

                    continue;

                }

            }

            return false;

        }

        return true;

}

equalsIgnoreCase方法是string类的忽略大小写的相等比较。

compareTo方法

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;

}

startWith方法

public boolean startsWith(String prefix) {

        return startsWith(prefix, 0);

}

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;

        // Note: toffset might be near -1>>>1.

        if ((toffset < 0) || (toffset > value.length - pc)) {

            return false;

        }

        while (--pc >= 0) {

            if (ta[to++] != pa[po++]) {

                return false;

            }

        }

        return true;

}