1. 程式人生 > >JAVA原始碼學習--String

JAVA原始碼學習--String

最近發四重新學習java的基礎,從基本型別以及裡面的各種方法開始看起,看的一本書《JAVA核心技術卷1,基礎知識》,這是第十版,講的JDK8的一些特性。
我在想我們建立物件的時候都是這樣進行建立的

People p = new People();
Integer i = new Integer();

但是String 和基本型別可以這麼寫

int i = 1;
String s = "ssss";//這種寫法,不是新建立的物件是在常量池中存放了一個ssss的字串,在棧裡面,如果沒有引用則消失

String 還可以這麼寫

String s = new String();//新建了一個String
的物件,這個是建立了一個新的String的物件,在堆裡面,不用的時候由垃圾回收器進行回收

這裡需要注意堆和棧的區別

看到String原始碼裡面有了個這個方法:

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

這個構造方法作用是什麼?構造方法傳進來的引數的型別是他自己?
發現String這個類中有兩個成員變數

 private final char value[];
    /** Cache the hash code for the string */
private int hash; // Default to 0

其中第二個hash他描述的是hash值,表示的是什麼意思?
下面是相應的方法

  /**
     * Returns a hash code for this string. The hash code for a
     * <code>String</code> object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using <code>int</code> arithmetic, where
<code>s[i]</code> is the * <i>i</i>th character of the string, <code>n</code> is the length of * the string, and <code>^</code> indicates exponentiation. * (The hash value of the empty string is zero.) * * @return a hash code value for this object. */ 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; }

方法好像是返回一個hase值,具體是什麼意思還是不太明白
然後我們深入的看了一下,發現Object類裡面也有一個方法

/**
     * Returns a hash code value for the object. This method is
     * supported for the benefit of hash tables such as those provided by
     * {@link java.util.HashMap}.
     * <p>
     * The general contract of {@code hashCode} is:
     * <ul>
     * <li>Whenever it is invoked on the same object more than once during
     *     an execution of a Java application, the {@code hashCode} method
     *     must consistently return the same integer, provided no information
     *     used in {@code equals} comparisons on the object is modified.
     *     This integer need not remain consistent from one execution of an
     *     application to another execution of the same application.
     * <li>If two objects are equal according to the {@code equals(Object)}
     *     method, then calling the {@code hashCode} method on each of
     *     the two objects must produce the same integer result.
     * <li>It is <em>not</em> required that if two objects are unequal
     *     according to the {@link java.lang.Object#equals(java.lang.Object)}
     *     method, then calling the {@code hashCode} method on each of the
     *     two objects must produce distinct integer results.  However, the
     *     programmer should be aware that producing distinct integer results
     *     for unequal objects may improve the performance of hash tables.
     * </ul>
     * <p>
     * As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer, but this implementation
     * technique is not required by the
     * Java<font size="-2"><sup>TM</sup></font> programming language.)
     *
     * @return  a hash code value for this object.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     java.lang.System#identityHashCode
     */
    public native int hashCode();

裡面對於這個方法的描述我也貼出來了,自己的英文不太好,看著百度翻譯看的,對於裡面的東西還是不太理解
Object是所有類的父類,所以String類裡面重寫了這個方法。
下面我們進行實驗會發現一個有趣的現象

String string1 = "aaa";
String string2 = new String(string1);
String string3 = new String("aaa");
System.out.println(string1==string2);//false 這個肯定是false,因為使用new時候是新建了一個String的物件,而string1是指向放在常量池中的一個地址(string2也是指向物件的一個地址)
但是他們的haseCode是一致的
System.out.println(string1.hashCode());
System.out.println(string2.hashCode());
System.out.println(string3.hashCode());//這三個個值是一樣的
/**
但是如果是我們自己新建的實體類的話
**/
People p1 = new People();
People p2 = new People();
People p3 = p2;
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());//這裡的值是不一樣的,為什麼?
System.out.println(p3.hashCode());//這裡p3和p2的值是一樣的

看一個文章說hashCode表示的是返回物件的地址值(不完全正確)
但是看Object這個類中的equals裡面就是直接比較的地址的啊
我知道為啥String 的hashCode返回的是一樣的了,因為他重寫了hashCode這個方法(開始自己竟然沒注意到。。)

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

hashCode不一樣肯定不是同一個物件,但是hashCode一樣的不一定是同一個物件

補充個意外的
JAVA建立物件的時候如果是基本的或者String資料型別需要放到常量池中,就會使用常量池中的屬性而不是在堆中新開闢一個空間。
比如說People這個類中有int eye;那麼如果people1 的eye=1;people2的eye =1;那麼這兩個都是使用棧中的一個地址的引用