Einige der Gründe wurden bereits aufgezeigt. Zum Beispiel die Tatsache, dass "... (fast) alle Operationen auf Byte, kurz, diese Grundelemente auf int heraufstufen" . Die naheliegende nächste Frage wäre jedoch: WARUM werden diese Typen befördert int
?
Um noch eine Ebene tiefer zu gehen: Die Antwort kann sich einfach auf den Java Virtual Machine-Befehlssatz beziehen. Wie in der Tabelle in der Java Virtual Machine-Spezifikation zusammengefasst , sind alle integralen arithmetischen Operationen wie Hinzufügen, Teilen und andere nur für den Typ int
und den Typ verfügbar long
und nicht für die kleineren Typen.
(Nebenbei: Die kleineren Typen ( byte
und short
) sind grundsätzlich nur für Arrays vorgesehen . Ein Array wie benötigt new byte[1000]
1000 Bytes und ein Array wie new int[1000]
4000 Bytes.)
Jetzt könnte man natürlich sagen: "... die naheliegende nächste Frage wäre: WARUM werden diese Anweisungen nur für int
(und long
) angeboten?" .
Ein Grund wird in der oben genannten JVM-Spezifikation erwähnt:
Wenn jede eingegebene Anweisung alle Laufzeitdatentypen der Java Virtual Machine unterstützen würde, gäbe es mehr Anweisungen, als in einem Byte dargestellt werden könnten
Darüber hinaus kann die Java Virtual Machine als Abstraktion eines realen Prozessors betrachtet werden. Die Einführung einer dedizierten arithmetischen Logikeinheit für kleinere Typen wäre die Mühe nicht wert: Sie würde zusätzliche Transistoren benötigen, könnte aber immer noch nur eine Addition in einem Taktzyklus ausführen. Die dominierende Architektur bei der Entwicklung der JVM war 32 Bit, genau richtig für 32 Bit int
. (Die Operationen, die einen 64-Bit- long
Wert beinhalten, werden als Sonderfall implementiert.)
(Hinweis: Der letzte Absatz ist unter Berücksichtigung einer möglichen Vektorisierung usw. etwas vereinfacht, sollte jedoch die Grundidee vermitteln, ohne zu tief in die Themen des Prozessordesigns einzutauchen.)
EDIT: Ein kurzer Nachtrag, der sich auf das Beispiel aus der Frage konzentriert, aber allgemeiner: Man könnte auch fragen, ob es nicht vorteilhaft wäre, Felder mit den kleineren Typen zu speichern . Zum Beispiel könnte man denken, dass Speicher durch Speichern Calendar.DAY_OF_WEEK
als gespeichert werden könnte byte
. Hier kommt jedoch das Java-Klassendateiformat ins Spiel: Alle Felder in einer Klassendatei belegen mindestens einen "Steckplatz" mit der Größe eins int
(32 Bit). (Die "breiten" Felder double
und long
belegen zwei Steckplätze). Wenn Sie also ein Feld explizit als Speicher deklarieren short
oder byte
nicht speichern.
int
. Wenn Sie einen Verweis auf eine andere Implementierung haben, würde ich die Antwort aktualisieren und den Link entsprechend einfügen.(Fast) Alle Operationen auf
byte
,short
fördert sieint
zum Beispiel, können Sie nicht schreiben:Arithmetik ist einfacher und unkomplizierter bei der Verwendung
int
, es muss nicht gegossen werden.In Bezug auf den Platz macht es einen sehr kleinen Unterschied.
byte
undshort
würde die Dinge komplizieren, ich denke nicht, dass sich diese Mikrooptimierung lohnt, da es sich um eine feste Anzahl von Variablen handelt.byte
ist relevant und nützlich, wenn Sie für eingebettete Geräte programmieren oder mit Dateien / Netzwerken arbeiten. Auch diese Grundelemente sind begrenzt. Was ist, wenn die Berechnungen in Zukunft ihre Grenzen überschreiten könnten? Versuchen Sie, über eine Erweiterung für dieCalendar
Klasse nachzudenken , die möglicherweise größere Zahlen entwickelt.Beachten Sie auch , dass in einem 64-Bit - Prozessoren, werden die Einheimischen in den Registern gespeichert und keine Ressourcen verwenden, so verwenden
int
,short
und andere Primitiven werden keinen Unterschied überhaupt machen. Darüber hinaus richten viele Java-Implementierungen Variablen * (und Objekte) aus.*
byte
Undshort
nehmen den gleichen Raum wieint
wenn sie lokale Variablen, Klassenvariablen oder sogar Instanz Variablen. Warum? Da in (den meisten) Computersystemen die Variablenadressen ausgerichtet sind. Wenn Sie beispielsweise ein einzelnes Byte verwenden, erhalten Sie tatsächlich zwei Bytes - eines für die Variable selbst und eines für das Auffüllen.byte
Nehmen Sie andererseits in Arrays 1 Byte,short
2 Bytes undint
vier Bytes, da in Arrays nur der Anfang und möglicherweise das Ende ausgerichtet werden müssen. Dies macht einen Unterschied, wenn Sie zum Beispiel verwenden möchtenSystem.arraycopy()
, dann werden Sie wirklich einen Leistungsunterschied feststellen.quelle
Weil arithmetische Operationen bei der Verwendung von ganzen Zahlen im Vergleich zu Kurzschlüssen einfacher sind. Angenommen, die Konstanten wurden tatsächlich durch
short
Werte modelliert . Dann müssten Sie die API folgendermaßen verwenden:Beachten Sie das explizite Casting. Kurzwerte werden implizit zu
int
Werten heraufgestuft, wenn sie in arithmetischen Operationen verwendet werden. (Auf dem Operandenstapel werden Kurzschlüsse sogar als Ints ausgedrückt.) Die Verwendung wäre ziemlich umständlich, weshalbint
Werte für Konstanten häufig bevorzugt werden.Im Vergleich dazu ist der Gewinn an Speichereffizienz minimal, da nur eine feste Anzahl solcher Konstanten existiert. Wir sprechen von 40 Konstanten. Wenn Sie den Speicher von
int
aufshort
ändern, werden Sie sicher sein40 * 16 bit = 80 byte
. Siehe diese Antwort als weitere Referenz.quelle
Wenn Sie die Philosophie verwenden, bei der integrale Konstanten in dem kleinsten Typ gespeichert werden, in den sie passen, hat Java ein ernstes Problem: Wenn Programmierer Code mit integralen Konstanten schreiben, müssen sie sorgfältig auf ihren Code achten, um zu überprüfen, ob der Typ von Die Konstanten sind wichtig. Wenn ja, schlagen Sie den Typ in der Dokumentation nach und / oder führen Sie die erforderlichen Typkonvertierungen durch.
Welche Vorteile können Sie mit dieser Philosophie erhoffen, nachdem wir ein ernstes Problem skizziert haben? Ich wäre nicht überrascht, wenn der einzige zur Laufzeit beobachtbare Effekt dieser Änderung der Typ wäre, den Sie erhalten, wenn Sie die Konstante durch Reflexion nachschlagen. (und natürlich alle Fehler, die von faulen / unwissenden Programmierern eingeführt werden, die die Typen der Konstanten nicht korrekt berücksichtigen)
Das Abwägen der Vor- und Nachteile ist sehr einfach: Es ist eine schlechte Philosophie.
quelle
Die Entwurfskomplexität einer virtuellen Maschine hängt davon ab, wie viele Arten von Vorgängen sie ausführen kann. Es ist einfacher, vier Implementierungen eines Befehls wie "Multiplizieren" zu haben - jeweils eine für 32-Bit-Ganzzahl, 64-Bit-Ganzzahl, 32-Bit-Gleitkomma und 64-Bit-Gleitkomma - als zusätzlich zu den oben genannten auch Versionen für die kleineren numerischen Typen. Eine interessantere Entwurfsfrage ist, warum es vier Typen geben sollte, anstatt weniger (alle Ganzzahlberechnungen mit 64-Bit-Ganzzahlen durchführen und / oder alle Gleitkommaberechnungen mit 64-Bit-Gleitkommawerten durchführen). Der Grund für die Verwendung von 32-Bit-Ganzzahlen besteht darin, dass Java auf vielen Plattformen ausgeführt werden sollte, auf denen 32-Bit-Typen genauso schnell wie 16-Bit- oder 8-Bit-Typen verarbeitet werden können, Operationen mit 64-Bit-Typen jedoch spürbar sind Langsamer.nur mit 32-Bit-Typen.
Bei der Durchführung von Gleitkommaberechnungen mit 32-Bit-Werten liegen die Vorteile etwas weniger auf der Hand. Es gibt einige Plattformen, auf denen eine Berechnung gefällt
float a=b+c+d;
Dies kann am schnellsten durchgeführt werden, indem alle Operanden in einen Typ mit höherer Genauigkeit konvertiert, hinzugefügt und das Ergebnis dann zur Speicherung wieder in eine 32-Bit-Gleitkommazahl konvertiert werden. Es gibt andere Plattformen, auf denen es effizienter wäre, alle Berechnungen mit 32-Bit-Gleitkommawerten durchzuführen. Die Entwickler von Java entschieden, dass alle Plattformen die gleichen Schritte ausführen sollten und dass sie die Hardwareplattformen bevorzugen sollten, für die 32-Bit-Gleitkommaberechnungen schneller sind als längere, obwohl dieser PC sowohl die Geschwindigkeit stark verschlechterte und Präzision der Gleitkomma-Mathematik auf einem typischen PC sowie auf vielen Maschinen ohne Gleitkommaeinheiten. Beachten Sie übrigens, dass abhängig von den Werten von b, c und d Zwischenberechnungen mit höherer Genauigkeit verwendet werden, wenn Ausdrücke wie die oben genannten berechnet werdenfloat a=b+c+d;
liefert manchmal Ergebnisse, die wesentlich genauer sind, als dies bei allen Zwischenoperanden der Fall wäre, die mitfloat
Genauigkeit berechnet wurden , liefert aber manchmal einen Wert, der ein wenig weniger genau ist. In jedem Fall entschied Sun, dass alles auf die gleiche Weise erfolgen sollte, und entschied sich für die Verwendung vonfloat
Werten mit minimaler Genauigkeit .Beachten Sie, dass die Hauptvorteile kleinerer Datentypen offensichtlich werden, wenn eine große Anzahl von ihnen zusammen in einem Array gespeichert wird. Selbst wenn es keinen Vorteil hätte, einzelne Variablen von Typen zu haben, die kleiner als 64 Bit sind, lohnt es sich, Arrays zu haben, die kleinere Werte kompakter speichern können. Wenn eine lokale Variable eher eine
byte
als eine ist, werdenlong
sieben Bytes gespeichert. Ein Array mit 1.000.000 Nummern enthält jede Nummer als abyte
und nicht alslong
Wellen 7.000.000 Bytes. Da jeder Array-Typ nur wenige Vorgänge unterstützen muss (insbesondere ein Element lesen, ein Element speichern, einen Bereich von Elementen innerhalb eines Arrays kopieren oder einen Bereich von Elementen von einem Array in ein anderes kopieren), erhöht sich die Komplexität, mehr zu haben Array-Typen sind nicht so schwerwiegend wie die Komplexität, mehr Typen direkt verwendbarer diskreter numerischer Werte zu haben.quelle
Eigentlich hätte es einen kleinen Vorteil. Wenn Sie eine haben
Dann benötigt eine typische JVM so viel Speicherplatz wie eine Klasse, die eine einzelne enthält
int
. Der Speicherverbrauch wird auf ein nächstes Vielfaches von 8 oder 16 Bytes gerundet (IIRC, das konfigurierbar ist), so dass die Fälle, in denen tatsächlich gespart wird, eher selten sind.Diese Klasse wäre etwas einfacher zu verwenden, wenn die entsprechenden
Calendar
Methoden a zurückgeben würdenbyte
. Aber es gibt keine solcheCalendar
Methoden, nurget(int)
die Zusammenarbeit soll kehrt einint
wegen anderen Bereichen. Jede Operation bei kleineren Typen fördert zuint
, so dass Sie viel Casting benötigen.Höchstwahrscheinlich geben Sie entweder auf und wechseln zu einem
int
oder schreiben Setter wieDann spielt die Art
DAY_OF_WEEK
sowieso keine Rolle.quelle