Die Gründe sind ziemlich kompliziert, aber sie liegen alle in den Details ( Kleingedrucktes, wenn Sie möchten) der Java-Sprachspezifikation.
Zunächst sagt der JLS 14.11 Folgendes über switch
Aussagen:
"Jede der switch-Anweisung zugeordnete Fallkonstante muss mit dem Typ des Ausdrucks der switch-Anweisung kompatibel sein ( §5.2 )."
Dies bedeutet , dass 'a'
zuordenbar sein muss Integer
und Byte
jeweils.
Das klingt aber nicht richtig:
Sie würden denken, dass da 'a'
einem zuweisbar sein sollte, Integer
weil char
-> int
Zuordnung legal ist. (Jeder char
Wert passt in eine int
.)
Sie würden denken, dass da 'a'
NICHT einer zuweisbar sein sollte, Byte
weil char
-> byte
Zuordnung NICHT legal ist. (Die meisten char
Werte passen nicht in ein Byte.)
In der Tat ist keines davon richtig. Um zu verstehen, warum, müssen wir lesen, was JLS 5.2 tatsächlich über das erlaubt, was in Zuweisungskontexten zulässig ist.
"Zuweisungskontexte ermöglichen die Verwendung einer der folgenden Optionen :
- eine Identitätsumwandlung (§5.1.1)
- eine sich erweiternde primitive Umwandlung (§5.1.2)
- eine erweiterte Referenzumwandlung (§5.1.5)
- eine erweiterte Referenzkonvertierung, gefolgt von einer Unboxing-Konvertierung
- eine sich erweiternde Referenzumwandlung, gefolgt von einer Unboxing-Umwandlung, gefolgt von einer sich erweiternden primitiven Umwandlung
- eine Boxumwandlung (§5.1.7)
- eine Boxumwandlung, gefolgt von einer erweiterten Referenzumwandlung
- eine Unboxing-Konvertierung (§5.1.8)
- eine Unboxing-Konvertierung, gefolgt von einer sich erweiternden primitiven Konvertierung. "
Um von zu 'a'
zu gelangen Integer
, müssten wir den Wert auf 1 erweitern char
und int
dann int
auf einen Wert setzen Integer
. Wenn Sie sich jedoch die zulässigen Kombinationen von Conversions ansehen, können Sie keine erweiterte primitive Conversion gefolgt von einer Box-Conversion durchführen.
Daher ist 'a'
to Integer
nicht erlaubt. Dies erklärt den Kompilierungsfehler im ersten Fall.
Sie würden denken, dass 'a'
to Byte
nicht erlaubt ist, da dies eine primitive Verengungskonvertierung beinhalten würde ... die überhaupt nicht in der Liste enthalten ist. In der Tat sind Literale ein Sonderfall. JLS 5.2 führt Folgendes aus.
"Wenn der Ausdruck ein konstanter Ausdruck ( §15.28 ) vom Typ Byte, Short, Char oder Int ist:
Eine sich verengende primitive Konvertierung kann verwendet werden, wenn die Variable vom Typ Byte, Short oder Char ist und der Wert des konstanten Ausdrucks im Typ der Variablen darstellbar ist.
Eine verengende primitive Konvertierung, gefolgt von einer Boxkonvertierung, kann verwendet werden, wenn die Variable vom Typ Byte
, Short
oder Character
ist und der Wert des konstanten Ausdrucks im Typbyte, Kurzschluss oder Zeichen darstellbar ist. "
Die zweite davon gilt 'a'
für Byte
, weil:
- ein Zeichenliteral ist ein konstanter Ausdruck, und
- Der Wert von
'a'
ist 97
dezimal und liegt innerhalb des Bereichs für byte
( -128
bis +127
).
Dies erklärt, warum im zweiten Beispiel kein Kompilierungsfehler vorliegt.
1 - Wir können nicht Box 'a'
auf ein Character
und dann erweitern Character
auf , Integer
weil Character
kein Java - Subtyp Integer
. Sie können eine erweiterte Referenzkonvertierung nur verwenden, wenn der Quelltyp ein Subtyp des Zieltyps ist.