2012-09-30 31 views
2

我一直在試圖瞭解一些API方法的工作確實String.equals()是如何工作的

下面

爲java.lang.String的類的equals方法的一個片段

能有人出來告訴我實際上代碼是如何比較兩個字符串的。 我明白了count的意義,但偏移意味着什麼。這些變量如何獲得價值?

就像當我創建一個字符串。這些如何初始化。

詳細的逐行描述以及如何以及何時實例變量,值,計數,偏移等被初始化?

public boolean equals(Object anObject) { 
    1014   if (this == anObject) { 
    1015    return true; 
    1016   } 
    1017   if (anObject instanceof String) { 
    1018    String anotherString = (String)anObject; 
    1019    int n = count; 
    1020    if (n == anotherString.count) { 
    1021     char v1[] = value; 
    1022     char v2[] = anotherString.value; 
    1023     int i = offset; 
    1024     int j = anotherString.offset; 
    1025     while (n-- != 0) { 
    1026      if (v1[i++] != v2[j++]) 
    1027       return false; 
    1028     } 
    1029     return true; 
    1030    } 
    1031   } 
    1032   return false; 
    1033  } 

回答

9

按道理

while (n-- != 0) { 
if (v1[i++] != v2[j++]) 
    return false; 
} 

相同

for (int i = 0; i < n; i++) { 
    if (v1[i] != v2[j]) 
     return false; 
    } 
} 

爲什麼JVM設計師們這樣我不知道這樣做。使用while循環的性能可能比for循環更好。它看起來很像我,所以也許寫這個的人有一個c背景。

Offset用於定位字符串在char數組中的起始位置。內部字符串存儲爲字符數組。這是value

if (v1[i++] != v2[j++]) 
    return false; 

檢查字符串的底層字符數組中的字符。

和逐行它是

如果refernce所指向的相同的對象是必須等號

1014   if (this == anObject) { 
1015    return true; 
1016   } 

如果對象是接着一個字符串檢查它們相等

1017   if (anObject instanceof String) { 

將以String形式傳入的參數進行強制轉換。

1018    String anotherString = (String)anObject; 

記住this.string

1019    int n = count; 

的長度,如果兩個字符串的長度匹配

1020    if (n == anotherString.count) { 

獲得字符數組(值是該陣列)

1021     char v1[] = value; 
1022     char v2[] = anotherString.value; 

找出在這裏數組字符串開始

1023     int i = offset; 
1024     int j = anotherString.offset; 

通過字符數組循環。如果值不同,則返回false

1025     while (n-- != 0) { 
1026      if (v1[i++] != v2[j++]) 
1027       return false; 
1028     } 

一切必須是真實的

1029     return true; 
1030    } 
1031   } 

如果不是String類型的然後他們不能等於

1032   return false; 
1033  } 

明白偏移和值查找字符串類

/** The value is used for character storage. */ 
private final char value[]; 

/** The offset is the first index of the storage that is used. */ 
private final int offset; 

/** The count is the number of characters in the String. */ 
private final int count; 

構造函數初始化這些變量。默認的構造函數代碼如下。你應該看到其他構造函數類似的東西。

/** 
    * Initializes a newly created {@code String} object so that it represents 
    * an empty character sequence. Note that use of this constructor is 
    * unnecessary since Strings are immutable. 
    */ 
public String() { 
    this.offset = 0; 
    this.count = 0; 
    this.value = new char[0]; 
} 

This是一個相當不錯的鏈接來看看

+0

這就是這麼幹淨..謝謝。 –

+0

還有一個問題,我找不到一個正在初始化這些實例變量的構造函數。有一個嗎?這是由JVM處理的。? –

+0

剛剛更新了默認ctor的字符串,這些初始化的答案 – RNJ

0

正如你可能知道字符串在Java中的處理是一個特殊的情況下,大部分的字符串是從字符串池分配的時間,所以它可能是這樣的情況,對於字符數組"I am Learning Java",一個字符串引用指向"I am Learning Java",則偏移將是0,其他字符串可能指向"am",因此偏移將是2由於一些本地代碼的處理其動初始化,所以我覺得在這個過程設置偏移。

而且(從字符串池共享內存時),你可以從代碼中看到

public String(String original) { 
     int size = original.count; 
     char[] originalValue = original.value; 
     char[] v; 
     if (originalValue.length > size) { 
      // The array representing the String is bigger than the new 
      // String itself. Perhaps this constructor is being called 
      // in order to trim the baggage, so make a copy of the array. 
      int off = original.offset; 
      v = Arrays.copyOfRange(originalValue, off, off+size); 
     } else { 
      // The array representing the String is the same 
      // size as the String, so no point in making a copy. 
      v = originalValue; 
     } 
     this.offset = 0; 
     this.count = size; 
     this.value = v; 
    } 

當新字符串是從舊的字符串創建的,它可能是舊字符串(本例中爲原始字符串)可能來自字符串池的情況,這就是爲什麼首先採用偏移量,然後複製整個數組以分配新內存(新字符串不會從字符串池共享內存)

另外你應該記住字符串是一個派生類型和字符串總是存儲在一個字符數組中,所以我們需要一個偏移量來確定字符串在字符數組中的起始位置。