2014-09-10 27 views
7

我在使用Java時發現了一個很奇怪的事情。也許這是一件普通的事情,但我不明白爲什麼它以這種方式工作。Java。爲什麼它與英語和斯拉夫語字符有所不同?

我有這樣的代碼:

Character x = 'B'; 
Object o = x; 
System.out.println(o == 'B'); 

它工作正常,輸出爲「真」。 然後我改變英語B至斯拉夫B(Б):

Character x = 'Б'; 
Object o = x; 
System.out.println(o == 'Б'); 

現在的輸出爲 「假」。怎麼來的? 順便說一下,如果我直接將x變量與'Б'進行比較,那麼輸出結果仍然是「真」,但是當我通過對象執行時,它的工作方式不同。

任何人都可以解釋這種行爲嗎?

回答

8

沒有拳擊 - 只使用char - 你會沒事的。同樣,如果您使用equals而不是==,則表示沒問題。問題在於你正在使用==來比較盒裝值的引用,它只是檢查參考身份。由於自動裝箱的方式,你會看到不同之處。你可以看到同樣的事情Integer

Object x = 0; 
Object y = 0; 
System.out.println(x == y); // Guaranteed to be true 

Object x = 10000; 
Object y = 10000; 
System.out.println(x == y); // *May* be true 

基本上都是「小」值已緩存的盒裝表示,而「較大」的值可能不是。

JLS 5.1.7

如果值p被裝箱是-128到127之間的字面int類型的整數包容(§3.10.1)或布爾值真或假(§3.10。 3)或'\ u0000'和'\ u007f'之間的字符字面值(§3.10.4),則讓a和b爲p的任意兩次裝箱轉換的結果。情況總是如此,a == b。

理想情況下,裝箱原始值總是會產生相同的參考。實際上,使用現有的實現技術可能不可行。上述規則是一種務實的妥協,要求某些共同的價值觀總是被裝箱成不可區分的對象。實現可能會緩存這些,懶惰或熱切。對於其他值,該規則不允許對程序員的盒裝值的身份進行任何假設。這允許(但不要求)共享這些引用的一部分或全部。請注意,允許共享long類型的整數文字,但不是必需的。

這可以確保在大多數情況下,行爲將成爲所需的行爲,而不會對性能造成不必要的損失,特別是在小型設備上。例如,較少的內存有限的實現可能會緩存所有值爲-32K到+ 32K的所有charshort值,以及intlong值。

關於「\u0000 and \ u007f`之間的字符文字」的部分保證了盒裝ASCII字符將被緩存,但不是非ASCII盒裝字符。

2

當你做

Character x = 'B' 

它調用Character.valueOf(C)

2: invokestatic #16     // Method java/lang/Character.valueOf:(C)Ljava/lang/Character; 

用於緩存

這種方法將範圍 '\ u0000的' 永遠的緩存值 '\ u007F' (含),並且可以緩存該範圍之外的其他值。

public static Character valueOf(char c) { 
    if(c <= 127) { // must cache 
     return CharacterCache.cache[(int)c]; 
    } 
    return new Character(c); 
} 

類似

相關問題