SORU
8 Temmuz 2014, Salı


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
8 Temmuz 2014, Salı


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

  1. JVM içinde tüm ilkel türler bit dizisi olarak temsil edilir. int türü 32 bit gösterilir, 16 bit char short türleri byte türü 8 bit ile temsil edilir.

  2. 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çin 0 negatif olmayan bir sayı (pozitif ya da sıfır) temsil eder ve 1 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 edilir

    00 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.

  3. , , *, char *shortbyte25 boolean 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, , * shortchar46 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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Awesome Toys TV

    Awesome Toys

    18 HAZİRAN 2014
  • RogerBuckChrist

    RogerBuckChr

    9 Temmuz 2011
  • WiseOwlTutorials

    WiseOwlTutor

    21 EKİM 2011