java String 源码解析

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

    // 内部结构存储是char数据,用于存储字符串的值
    private final char value[];

    // 缓存字符串的 hash code 
    private int hash; // Default to 0

   
    private static final long serialVersionUID = -6849794470754667710L;

     // 以String 为参数的构造方法
     public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
     }
    // 以char[]数组为参数的构造方法 
     public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }
    // 以StringBuffer为参数的构造方法
    public String(StringBuffer buffer) {
        synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
    }
    // 以StringBuilder为参数的构造方法
    public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }
   
    /**
     * String 类型重写了Object 中的equals()方法,equals()方法需要传递一个Object类型的参数
     * 值,在比较时会先通过instanceof 判断是否String类型,如果不是则会直接返回false
     */
    public boolean equals(Object anObject) {
        // 对象引用地址相同直接返回 true
        if (this == anObject) {
            return true;
        }
        // 判断入参 anObject 类型是否为String类型,若不是 则返回 false
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                // 把两个字符串转换成char[]数组进行对比
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                // 循环比较两个字符串的每一个字符串
                while (n-- != 0) {
                    // 若其中有一个字符串不相等返回false,否则继续比较
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                // 当所有字符都相等的时候返回true 
                return true;
            }
        }
        return false;
    }
    /**
     *比较两个字符串
     * 若两个字符串分别存储1 和 2,返回的值为 -1
     * 若两个字符串分别存储1 和 1,返回的值为 0
     * 若两个字符串分别存储2 和 1,返回的值为 1
     */
    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        // 获取两个字符串长度最短的那个 int的值
        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;
    }

}

从源码 可以看出 ,compareTo() 方法 和 equals() 方法都是用于比较连个字符串的,但他们有两点不同:

1.equals() 可以接收一个Object类型的参数,而 compareTo() 只能接收一个String类型的参数

2.equals() 返回值为boolean类型, 而compareTo()返回值则为int类型

3. equals()方法返回true的时候表示两个字符串相等,comparaTo() 返回0 的时候表示两个字符串相等

拓展:

 1.  == 和equals() 的区别

== 对于基本数据类型来说,是用户比较 "值" 是否相等

对于引用数据类型来说,是用户比较引用地址是否相同的

通过查看 Object中的equals( ) 方法

public class Object {
     public boolean equals(Object obj) {
        return (this == obj);
     }
}

equals()方法其实底层就是使用==, 而String重写了equals() 方法把它修改成比较两个字符串的值是否相等

 

String 在JVM中的存储:


        String str1 = new String("java");
        String str2 = str1.intern();
        String str3 = "java";
        System.out.println(str1 == str2); // false
        System.out.println(str2 == str3); // true

String常见的创建方式有两种:

直接赋值的方式“Strings1="Java";”和“Strings2=newString("Java");”的方式,但两者在JVM的存储区域却截然不同.

在JDK1.8中,变量str1会先去字符串常量池中找改字符串 "java",如果存在改字符串,则直接返回常量句柄,如果没有此字符串,则会

现在常量池中创建此字符串,然后再返回常量句柄; 而变量str2是直接在堆上创建一个变量, 只有调用intern() 方法擦灰把此字符串保存到常量池中

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章