2013-04-17 30 views
19

在Java字符串source code,沒有幾個地方有這樣的評論指出:「偏移量或計數可能接近-1 >>> 1」。這是什麼意思

// Note: offset or count might be near -1>>>1. 

請看下面的例子:

public String(char value[], int offset, int count) { 
    if (offset < 0) { 
     throw new StringIndexOutOfBoundsException(offset); 
    } 
    if (count < 0) { 
     throw new StringIndexOutOfBoundsException(count); 
    } 
    // Note: offset or count might be near -1>>>1. 
    if (offset > value.length - count) { 
     throw new StringIndexOutOfBoundsException(offset + count); 
    } 
    this.offset = 0; 
    this.count = count; 
    this.value = Arrays.copyOfRange(value, offset, offset+count); 
} 

正如我們所看到的,offsetvalue.lengthcount都是int,因此該值可能是-1,0,1或任何其他整數。評論中的「near」和「>>>」意味着什麼,我在這裏錯過了什麼?

+6

'-1 >>> 1'是混淆的說法'Integer.MAX_VALUE' – soulcheck

回答

20

-1>>>1 == 2147483647是您可以在Java中使用的最大值int

換句話說,-1>>>1 == Integer.MAX_VALUE。當你的數值接近這樣的限制時,你增加了獲得意外結果的機會。例如,int a = (-1>>>1); System.out.println(a < a + 1);打印false因爲整數溢出,儘管人們可以預期,代碼總是打印自true,在純數學,對於任何整數n這是事實,n < n + 1

這段代碼的作者只是解釋了他(WISE)決定寫

if (offset > value.length - count) 

代替類似的前瞻性,但並非等同

if (offset + count > value.length) 

這最後的版本可能會導致整數溢出,這對於後面的代碼來說可能是一個巨大的麻煩。他警告說,有可能至少有一個offsetcount可能是接近Integer.MAX_VALUE的值,這增加了溢出的可能性。

隨着第一個版本(在字符串你提到的源代碼中使用的一個),永遠不會有溢出:你肯定知道這兩個offsetcount爲正或0,因爲以前的檢查,並value.length是也是正數或0,因爲在Java中數組的長度總是正數或0,所以不會發生溢出問題!

除了記錄選擇之外,作者還警告其他開發人員(包括他未來的自己),說明該行的寫法是非常具體的原因,以避免任何試圖用(可能更自然),其次,引入錯誤的版本不正確。

+0

中,這是從寫這個代碼的作者深思熟慮的。 – zynick

+0

只是好奇,爲什麼作者不寫作「抵消或計數可能接近Integer.MAX_VALUE」呢?儘管Integer.MAX_VALUE含糊不清,至少可以更容易理解。畢竟,評論的要點是如果代碼發生變化,可能的整數溢出的未來開發者會發出溢出警告。 – zynick

+0

@zynick:「容易理解」是相對的,基於你來自哪裏,你有什麼經驗。請記住:這不是通過文檔團隊進行優化的公開文檔。這只是一個JDK開發人員爲所有未來的開發人員編寫的代碼而寫的說明。這是非正式的,不一定是最好的方式。 –

5

你可能想看看Bitwise and Bit Shift Operators有關>>>操作說明:

無符號向右移位運算符「>>>」移動零到 最左邊的位置

說你有:

int a = -1; 
a = a >>> 1; 
System.out.println(a); 

然後a將是2147483647(這是Integer.MAX_VALUE

爲什麼?

由於>>>運算符填充零和只有零,無論正數和負數。因此,舉例來說,如果您有:

12 >>> 2

(00000000 00000000 00000000 000011 00 >>> 2),那麼結果是3

(這是00000000 00000000 00000000 00000011)。

所以,如果你會做:

System.out.println(Integer.toBinaryString(-1>>>1)); 

這將打印:

1111111111111111111111111111111 

,當然還有,將其轉換爲十進制,這是2147483647

作爲@ BrunoReis(+1)在他的回答中解釋說,這樣做的原因是爲了防止可能的整數溢出問題。

+0

爲了更好的理解,你應該解釋什麼是二進制補碼錶示。現在不明白爲什麼1111111111111111111111111111111是-1,而0111111111111111111111111111111是最大值。 – Mikhail

+2

謝謝你解釋這個位是如何工作的,我不小心把它留在了我的大學 – zynick

相關問題