Neden bir Integer sarıcısı üzerindeki Java anahtarında, 'char' durumu derlenmez, ancak anahtar Byte bittiğinde derleme tamam mı?


18

Derlemez:

void test(Integer x) {
      switch (x) {
          case 'a':
      }
}

Derleme Tamam:

void test(Byte x) {
      switch(x) {
          case 'a':
      }
}

1
Tamsayı 4 bayt, karakter 2 bayttır. İlk durumda, hangi karakteri yazarsanız yazın, tamsayıdan daha küçüktür. Ancak ikinci durumda, yazdığınız karakter maksimum bayttan daha büyük olabilir ve bu durumda hiçbir zaman çalıştırılmaz.
Jaroslaw Pawlak

Bu açıklama yanlış. Nitekim, 2 örnekte, kod 'a'durumda olacak durumda yürütülecek xbayt olduğunu 97. (Bana inanmıyorsanız deneyin.) Gerçek açıklama için cevabımı görün.
Stephen C

Yanıtlar:


19

Sebepleri oldukça karmaşıktır, ancak hepsi Java Dil Spesifikasyonunun ayrıntılarındadır ( isterseniz ince baskı ).

İlk olarak, JLS 14.11switch ifadeler hakkında şunları söylüyor :

"Switch ifadesiyle ilişkilendirilen her büyük harf sabiti, switch ifadesinin Expression ( §5.2 ) türüyle uyumlu bir atama olmalıdır ."

Bu, sırasıyla ve 'a'atanabilir olması gerektiği anlamına gelir .IntegerByte

Ama bu doğru gelmiyor:

  • Sen düşünürdüm beri bu 'a' olmalıdır bir atanabilir IntegerNEDENİYLE char> - int atama yasaldır. (Herhangi bir chardeğer bir int.

  • Sen düşünürdüm beri bu 'a' olmamalı bir atanabilir ByteNEDENİYLE char> - byte atama yasal DEĞİLDİR. (Çoğu chardeğer bir bayta sığmaz.)

Aslında bunların ikisi de doğru değil. Nedenini anlamak için , atama bağlamında izin verilenler hakkında JLS 5.2'nin gerçekte ne olduğunu okumalıyız .

"Atama bağlamları aşağıdakilerden birinin kullanılmasına izin verir :

  • bir kimlik dönüşümü (§5.1.1)
  • genişleyen ilkel dönüşüm (§5.1.2)
  • genişleyen referans dönüşümü (§5.1.5)
  • genişleyen bir referans dönüşümü ve ardından kutudan çıkarma dönüşümü
  • genişleyen referans dönüşümü ve ardından kutudan çıkarma dönüşümü, ardından genişleyen ilkel dönüşüm
  • bir boks dönüşümü (§5.1.7)
  • bir boks dönüşümü ve ardından genişleyen referans dönüşümü
  • kutudan çıkarma dönüşümü (§5.1.8)
  • kutudan çıkarma dönüşümü ve ardından genişleyen ilkel dönüşüm. "

Gitmek için 'a'için Integeriçin, ihtiyacımız 1 genişletmek charbir değer intdaha sonra boks intbir etmek Integer. Ancak, izin verilen dönüşüm kombinasyonlarına bakarsanız, daha geniş bir ilkel dönüşüm ve ardından bir boks dönüşümü yapamazsınız.

Bu nedenle ' 'a'e Integerizin verilmez. Bu, ilk durumda derleme hatasını açıklar.

Sen düşünürdüm 'a'için Byteizin olduğunu hiç listesinde olmayan ilkel daralması dönüşüm ... içerir çünkü. Aslında değişmez değerler özel bir durumdur. JLS 5.2 şunları söylemeye devam ediyor.

"Ayrıca, ifade, byte, short, char veya int türünde sabit bir ifadeyse ( §15.28 ):

  • Değişken byte, short veya char tipindeyse ve sabit ifadenin değeri değişken tipinde temsil edilebilirse daraltıcı bir ilkel dönüşüm kullanılabilir.

  • Değişken türde ise bir boks dönüştürülmesi takip bir daralma ilkel dönüşüm kullanılabilir Byte, Shortya da Character, ve sürekli ifadesinin değeri kısa, tip byte sunulabilen veya karakter sırasıyla ".

Bunlardan ikinci uygulanır 'a'için Byte, çünkü:

  • bir karakter değişmezi sabit bir ifadedir ve
  • değeri 'a'olan 97aralık içinde olan, ondalık byte( -128kadar +127).

Bu, ikinci örnekte neden derleme hatası olmadığını açıklar.


1 - Biz kutu edemez 'a'bir etmek Characterve sonra genişletmek Characteriçin Integerçünkü Characterbir Java alt tür değil Integer. Genişletme referans dönüşümünü yalnızca kaynak türü hedef türün bir alt türüyse kullanabilirsiniz.


intAnahtar türü olarak kullanabilir miyiz ? ( char -> intizin verilen ilkel genişleme olduğu için)
AjahnCharles
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.