Warum ist "int i = 2147483647 + 1;" OK, aber "Byte b = 127 + 1;" ist nicht kompilierbar?

126

Warum ist int i = 2147483647 + 1;OK, aber byte b = 127 + 1;nicht kompilierbar?

Goku
quelle
16
Ich habe auch einen echten Zweifel: Warum ist der byteDatentyp so schmerzhaft?!
BoltClock
9
Es ist definitiv ein Designfehler, der bytesigniert statt nicht signiert ist.
unwiderlegbar
4
@BoltClock Es ist nur dann ein Schmerz, wenn Sie nicht wissen, wie man es richtig benutzt. stackoverflow.com/questions/397867/…
starblue
2
@starblue, gibt es ein Beispiel aus der Praxis, in dem der Java-Bytetyp anwendbar ist?
Thorbjørn Ravn Andersen
Wenn Daten vorhanden sind, die als Byte angegeben sind, verwenden Sie byteaus Gründen der Übersichtlichkeit Java , z. B. in Parametern. In diesem Fall kann die Tatsache, dass Sie keine intWerte zuweisen können, sogar einige Fehler verursachen. Oder verwenden Sie byte, um Platz in Arrays zu sparen. Ich würde nicht bytefür einen einzelnen Wert verwenden, der zufällig in ein Byte passt.
Starblue

Antworten:

172

Konstanten werden als Ints ausgewertet, laufen also 2147483647 + 1über und geben Ihnen ein neues Int, das zugewiesen werden kann int, während es 127 + 1auch als intgleich ausgewertet 128wird und dem es nicht zugewiesen werden kann byte.

MByD
quelle
10
Eigentlich habe ich heute einige Java-Puzzler gelesen , einschließlich eines Puzzles dazu ... Siehe hier: javapuzzlers.com/java-puzzlers-sampler.pdf - Puzzle 3
MByD
3
Das Problem ist der Typ intaufgrund der binären numerischen Werbung, der Wert 127ist ein roter Hering.
Starblue
Ich würde es vorziehen, Konstanten mit unendlicher Genauigkeit auszuwerten und auch einen Fehler bei int i = 2147483647 + 1 zu geben;
Eduardo
@MByD: Wie Sie sagten " while 127 + 1 also evaluated as int equals to 128, and it is not assignable to byte.", bedeutet dies, dass 50 + 1 als bewertet wird byteund daher zugewiesen werden kann byte?
Bhushan
1
@ 10101010 - nicht genau. es kann dem Byte zugewiesen werden, aber zuerst (gemäß dem Standard) wird es als int ausgewertet.
MByD
35

Das Literal 127 bezeichnet einen Wert vom Typ int. Dies gilt auch für das Literal 1. Die Summe dieser beiden ist die Ganzzahl 128. Das Problem im zweiten Fall besteht darin, dass Sie dies einer Variablen vom Typ Byte zuweisen. Es hat nichts mit dem tatsächlichen Wert der Ausdrücke zu tun. Es hat damit zu tun, dass Java keine Zwänge unterstützt (*). Sie müssen einen Typecast hinzufügen

byte b = (byte)(127 + 1);

und dann kompiliert es.

(*) Zumindest nicht von der Art String-to-Integer, Float-to-Time, ... Java unterstützt Zwänge, wenn sie in gewissem Sinne verlustfrei sind (Java nennt dies "Verbreiterung").

Und nein, das Wort "Zwang" musste nicht korrigiert werden. Es wurde dabei sehr bewusst und richtig gewählt. Aus der nächstgelegenen Quelle (Wikipedia): "In den meisten Sprachen wird das Wort Zwang verwendet, um eine implizite Konvertierung entweder während der Kompilierung oder zur Laufzeit zu bezeichnen." und "In der Informatik sind Typkonvertierung, Typumwandlung und Zwang verschiedene Möglichkeiten, eine Entität eines Datentyps implizit oder explizit in eine andere zu ändern."

Erwin Smout
quelle
Ihr Codebeispiel sollte wahrscheinlich Byte b = (Byte) 127 + 1 sein; In Ihrem Beispiel wird nur der int-Wert von 128 in einen Byte-Wert umgewandelt.
NKCSS
6
@NKCSS - Ich glaube nicht, dass Sie Recht haben, dies - wirf (byte)(127 + 1)128 (Ganzzahl) in ein Byte, während dies (byte)127 + 1die 127 in ein Byte umwandelt, aber dann wieder in ein Int, da es zu 1 (Int) und dir hinzugefügt wird Holen Sie sich 128 (int) und Fehler bleibt.
MByD
6

Als Beweis für @MByD:

Der folgende Code wird kompiliert:

byte c = (byte)(127 + 1);

Denn obwohl der Ausdruck (127 + 1)int ist und über den Gültigkeitsbereich hinausgeht, wird bytedas Ergebnis in umgewandelt byte. Dieser Ausdruck erzeugt -128.

AlexR
quelle
3

JLS3 # 5.2 Zuweisungskonvertierung

(Variable = Ausdruck)

Wenn der Ausdruck ein konstanter Ausdruck (§15.28) vom Typ Byte, Short, Char oder Int ist:

Eine verengende primitive Konvertierung kann verwendet werden, wenn der Typ der Variablen Byte, Short oder Char ist und der Wert des konstanten Ausdrucks im Typ der Variablen darstellbar ist.


Ohne diese Klausel könnten wir nicht schreiben

byte x = 0;
char c = 0;

Aber sollten wir dazu in der Lage sein? Das glaube ich nicht. Es gibt ziemlich viel Magie bei der Bekehrung unter Primitiven, man muss sehr vorsichtig sein. Ich würde mir alle Mühe geben, um zu schreiben

byte x = (byte)0;
unwiderlegbar
quelle
Was die Frage betrifft, sollten wir in der Lage sein ... Ich sehe nicht wirklich etwas falsch daran, byte x = 0aber andererseits bin ich ein C-Programmierer.
Grady Player
Ich könnte vielleicht ein Argument gegen char c = 0 sehen, aber warum ist Byte x = 0 falsch?
Michael Burge
Es ist irreführend für ungeübte Augen, wenn sie denken, dass sie einer Byte-Variablen ein Byte 0 zuweisen. In diesem Beispiel nicht viel Schaden, aber im Allgemeinen kann das Arbeiten mit Byte / Short / Char aufgrund impliziter Konvertierungen sehr verwirrend werden. Sie sind viel komplizierter als man denkt. Ich möchte so viel Klarheit wie möglich in meinem Code haben, keine Unsicherheit einführen, um ein paar Tastenanschläge zu speichern.
unwiderlegbar
Gilt eine ähnliche Regel, wenn die Verengung der primitiven Konvertierung von long nach int ist, z. B. int i = 1 + 0L? Fragen Sie einfach, weil Ihr zitierter Text diesen Fall ausdrücklich auslässt.
Erwin Smout
@Erwin nein, int i=0List illegal.
Unbestreitbarer