Neden Java '(int)(char)(bayt)-2' üretmek 65534 mu?
Bir iş için teknik test bu soru ile karşılaştım. Verilen aşağıdaki kod örneği:
public class Manager {
public static void main (String args[]) {
System.out.println((int) (char) (byte) -2);
}
}
65534 olarak çıktı veriyor.
Bu davranış; 0 ve pozitif tek sayılar aynı verim değeri negatif değerler için bir SOP girilen anlamını gösterir. Bayt oyuncuları burada önemsİzdİr; olmadan denedim.
Neler oluyor burada? benim sorum:
CEVAP
Burada neler olduğunu anlamak için, önce kabul etmemiz gereken bazı koşullar vardır. Aşağıdaki işe yarar bir anlayışla, gerisi basit çıkarım
JVM içinde tüm ilkel türler bit dizisi olarak temsil edilir.
int
türü 32 bit gösterilir, 16 bitchar
short
türleribyte
türü 8 bit ile temsil edilir.Tüm JVM sayı
char
türünün tek imzasız olduğu imzalı, "sayı". Bir dizi imzaladı,en yüksekbu sayının işaretini göstermek için kullanılır. Bu en yüksek bit için0
negatif olmayan bir sayı (pozitif ya da sıfır) temsil eder ve1
negatif bir sayı temsil eder. Ayrıca, imzalı sayılarla, negatif bir değerinvertedpozitif sayıların incrementation sipariş için. Örneğin,byte
pozitif bir değer aşağıdaki gibidir: bit ile temsil edilir00 00 00 00 => (byte) 0 00 00 00 01 => (byte) 1 00 00 00 10 => (byte) 2 ... 01 11 11 11 => (byte) Byte.MAX_VALUE
negatif sayılar ters olduğu için biraz süre sipariş:
11 11 11 11 => (byte) -1 11 11 11 10 => (byte) -2 11 11 11 01 => (byte) -3 ... 10 00 00 00 => (byte) Byte.MIN_VALUE
Bu ters gösterimde de olumsuz aralığı ek bir numara ikincisi 20 ** numarasını temsili içeren olumlu aralığına göre barındırabilir açıklıyor. Unutmayın, bu sadece bir meselediryorumlamabir bit deseni. Negatif sayılar farklı not edebilirsiniz, ama negatif sayılar için bu ters gösterimde küçük bir örnek, daha sonra görmek mümkün olacak gibi oldukça hızlı bazı dönüşümler için oldukça kullanışlı.
Belirtildiği gibi, bu
char
türü için geçerli değildir.char
tür negatif olmayan ""65535
23*. sayısal dizi ile bir Unicode karakteri temsil eder Bu sayı her 16-bits Unicode bir değer ifade eder., , *,
char
*short
byte
25boolean
türleri arasında dönüştürürken JVM veya eklemek bit kesmek gerekiyor.Eğer hedef türü tarafından temsil edilir daha fazla bit daha türünden hangisi dönüştürülmüş, sonra JVM sadece doldurur ek yuvası ile değeri en yüksek bit verilen değer (hangi gösterir imza):
| short | byte | | | 00 00 00 01 | => (byte) 1 | 00 00 00 00 | 00 00 00 01 | => (short) 1
Ters gösterimde, bu strateji sayesinde de negatif sayılar için çalışır:
| short | byte | | | 11 11 11 11 | => (byte) -1 | 11 11 11 11 | 11 11 11 11 | => (short) -1
Bu şekilde, değeri işareti korunur. Bir JVM için bu uygulama detaylara girmeden, bu model bir döküm açıkçası avantajlı bir ucuz shift operation tarafından gerçekleştirildiği için izin verdiğini unutmayın.
Bu kurala bir istisna değildirgenişletmedaha önce de söylediğimiz gibi, imzasız olan
char
bir tür. Bir dönüşümdanchar
her zaman bir iz ve böylece ters bir gösterim için gerek yok dedik çünkü0
ile ek bit doldurarak uygulanır.int
char
bir dönüşüm bu nedenle olarak gerçekleştirilir:| int | char | byte | | | 11 11 11 11 | 11 11 11 11 | => (char) \uFFFF | 00 00 00 00 | 00 00 00 00 | 11 11 11 11 | 11 11 11 11 | => (int) 65535
Orijinal türü hedef türü daha fazla bit, ilave bit sadece kesilmiş. Özgün değeri hedef değer içine sığacak kadar uzun, bu iyi,
short
byte
için: aşağıdaki dönüşüm için örnek olarak çalışıyor| short | byte | | 00 00 00 00 | 00 00 00 01 | => (short) 1 | | 00 00 00 01 | => (byte) 1 | 11 11 11 11 | 11 11 11 11 | => (short) -1 | | 11 11 11 11 | => (byte) -1
Eğer değeri iseçok büyükyaçok küçükbu değil uzun iş:
| short | byte | | 00 00 00 01 | 00 00 00 01 | => (short) 257 | | 00 00 00 01 | => (byte) 1 | 11 11 11 11 | 00 00 00 00 | => (short) -32512 | | 00 00 00 00 | => (byte) 0
Bu daralma döküm bazen tuhaf sonuçlara neden nedeni budur. Daralma bu şekilde uygulanır neden merak edebilirsiniz. JVM bir sayı aralığı kontrol ve aynı işareti en büyük gösterilebilir değere uymayan bir dizi döküm tercih ederseniz daha kolay olacağını söyleyebiliriz. Ancak, bu pahalı bir işlemdir ne branching gerektirecektir. Bu this two's complement notation ucuz aritmetik işlemler olanak sağladığı için özellikle önemlidir.
Tüm bu bilgi ile, örnek numarası ile -2
ne olacağını görürüz:
| int | char | byte |
| 11 11 11 11 11 11 11 11 | 11 11 11 11 | 11 11 11 10 | => (int) -2
| | | 11 11 11 10 | => (byte) -2
| | 11 11 11 11 | 11 11 11 10 | => (char) \uFFFE
| 00 00 00 00 00 00 00 00 | 11 11 11 11 | 11 11 11 10 | => (int) 65534
Gördüğünüz gibi, byte
dökme char
oyuncular aynı parçaları kesmek gibi gereksiz.
Bu da eğer tüm bu kuralları daha resmi bir tanım isterseniz 56**.
Son bir not: boyutu mutlaka onun anısına bu türü temsil eden JVM tarafından ayrılmış bit miktarını temsil etmez Bir tip biraz. Nitekim, JVM*, byte
, , * short
char
46 ve int
türleri arasında ayırım yapmaz. Hepsi sanal makine sadece bu dökümler taklit nereye JVM-aynı tür ile temsil edilmektedir. Bir yöntemin işlenen yığını (bir yöntem içinde herhangi bir değişken gibi), adlı türlerinin tüm değerleri 32 bit tüketir. Bu ancak herhangi bir JVM uygulayıcısı olacak işleyebilir hangi diziler ve nesne alanları için geçerli değildir.
Neden char[] şifreler için Dize Java t...
Neden Java API yerine veya bayt int kı...
Neden hiçbir bayt veya Java içinde kıs...
Neden belirli Unicode karakterler içer...
Neden Java geçici değişkenler var mı?...