2014-09-10 19 views
7

Java ile çalışırken oldukça garip bir şey buldum. Belki de sıradan bir şeydir, ama neden böyle çalıştığını anlamıyorum. Düzgün çalışır ve çıkış "doğru" olduğunuJava. Neden ingilizce ve slav karakterleri ile farklı çalışır?

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

:

Böyle bir kodu var.

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

Şimdi çıkış "yanlış" dir: Sonra Slav B (Б) için ingilizce B değiştirin. Nasıl olur? Bu arada, x değişkenini doğrudan "Б" ile karşılaştırırsam, çıktı hala "true" olur, ancak bunu bir Object aracılığıyla yaptığımda farklı şekilde çalışır.

Bu davranışı açıklayabilir misiniz?

cevap

8

Kutu olmadan - sadece char kullanıyorsunuz - iyiyim. Benzer şekilde, == yerine equals kullanırsanız iyi olur. Sorun, yalnızca referans kimliğini kontrol eden == kullanarak kutulu değerler için referansları karşılaştırmanızdır. Otomatik kutunun çalışma şekli yüzünden bir fark görüyorsunuz. Sen Integer ile aynı şeyi görebilirsiniz:

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 

Temelde "küçük" değerleri önbelleğe sahip kutulu temsillerini, oysa "büyük" değerler olmayabilir. JLS 5.1.7 kaynaktan

:

p değeri kutulaştırılmıştır ise -128 ve 127 arasında tip int literal bir tamsayıdır dahil (§3.10.1) ya da mantıksal doğru hazır veya yanlış (§3.10. 3) ya da '\ u0000' ile '\ u007f' (§3.10.4) arasında bir karakter değişkeni, ardından a ve b, p'nin iki boks dönüşümünün sonuçları olsun. Bu her zaman bir == b. İdeal olarak, bir ilkel değerin boks edilmesi her zaman aynı referansı verirdi. Uygulamada, bu, mevcut uygulama teknikleri kullanılarak uygulanabilir olmayabilir. Yukarıdaki kural, belirli ortak değerlerin her zaman ayırt edilemez nesneler olarak kutlanmasını gerektiren, pragmatik bir uzlaşmadır. Uygulama bunları tembel ya da hevesle önleyebilir. Diğer değerler için kural, programcının kısmındaki kutulu değerlerin kimliği hakkındaki varsayımlara izin vermez. Bu, bu referansların bazılarının veya hepsinin paylaşılmasına izin verir (ancak bunu gerektirmez). long türünde tamsayı hazırlayıcılarına, paylaşılmak üzere izin verilir, ancak gerekli değildir. Bu, çoğu durumda, özellikle küçük cihazlarda, gereksiz bir performans cezası verilmeksizin, davranışın arzu edileni olmasını sağlar. Daha az bellek sınırlı uygulamalar, örneğin, char ve short değerlerinin yanı sıra int ve long değerlerini -32K ila + 32K aralığında önbelleğe alabilir.

önbelleğe edilecektir ASCII karakterleri kutulu garantiler, fakat ASCII olmayan kutulu karakterler "\u0000 and \ u007f` arasındaki değişmez bir karakter" hakkında parçası

.

2

Eğer

Character x = 'B' 

o

Bu yöntem olacak '\ u0000' aralığında daima önbellek değerleri için '\ u007F' önbelleğe Character.valueOf(C)

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

çağırır ne zaman dahil, ve bu aralığın dışındaki diğer değerleri önbelleğe alabilir.

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

Benzer

İlgili konular