Java Zahlen
Arbeite mit numerischen Typen in Java — int, long, float, double — und verstehe Präzision, Überlauf und die Number-Klasse.
Java unterscheidet zwischen ganzzahligen und Gleitkommazahlen, und innerhalb jeder Familie gibt es mehrere Größen. Die Wahl des richtigen Typs ist sowohl für Korrektheit (Präzision, Wertebereich) als auch für die Leistung wichtig. Dieses Kapitel ist ein gezielter Durchgang durch die numerischen Typen, ihre Literale, Konvertierungen und die Fallstricke, die Anfänger überraschen. Es setzt voraus, dass du bereits weißt, wie man eine Variable deklariert, und die vollständige Liste der primitiven Datentypen gesehen hast.
Die numerischen Primitiven
| Typ | Bits | Wertebereich | Standard-Literalform |
|---|---|---|---|
byte | 8 | -128 bis 127 | byte b = 10; |
short | 16 | -32.768 bis 32.767 | short s = 30_000; |
int | 32 | -2³¹ bis 2³¹-1 (≈ ±2,1 Milliarden) | int i = 1_000_000; |
long | 64 | -2⁶³ bis 2⁶³-1 | long l = 9_000L; |
float | 32 | IEEE 754 einfache Genauigkeit (~7 Stellen) | float f = 3.14f; |
double | 64 | IEEE 754 doppelte Genauigkeit (~16 Stellen) | double d = 3.14; |
Im alltäglichen Java:
- Verwende
intfür Zähler, Indizes und die meisten ganzzahligen Werte. - Verwende
long, wenn der Wert ~2 Milliarden überschreiten könnte (Dateigrößen, Millisekunden seit der Epoche, ID-Generatoren). - Verwende
doublefür Gleitkomma-Arithmetik. - Verwende
floatnur, wenn der Speicher knapp ist oder eine API es erfordert.
Ganzzahl-Literale
Einfache Ziffern sind int:
int answer = 42;
int million = 1_000_000; // underscores are ignoredSuffix L (Großbuchstabe bevorzugt) für long:
long big = 9_000_000_000L;Präfix 0x für Hexadezimal, 0b für Binär, 0 für Oktal:
int hex = 0xFF; // 255
int bin = 0b1010; // 10
int oct = 0755; // 493 — be careful, easy to write by accident(Oktal-Literale sind eine häufige Fehlerquelle — 0123 ist nicht 123, sondern 83. Vermeide führende Nullen, es sei denn, du meinst wirklich Oktal.)
Gleitkomma-Literale
Einfache Dezimalzahlen sind double:
double pi = 3.14159;
double e = 2.71828;Suffix f für float, d für explizites double (optional):
float pif = 3.14f;
double pid = 3.14d;Wissenschaftliche Notation funktioniert ebenfalls:
double avogadro = 6.022e23;
double tiny = 1.0e-9;Konvertierung zwischen numerischen Typen
Java führt automatisch eine Erweiterungskonvertierung durch, wenn ein kleinerer Typ in einen größeren fließt (kein Datenverlust möglich):
int x = 7;
double promoted = x; // 7.0 — int widens to double automaticallyIn die andere Richtung ist es eine einengende Konvertierung: Der Wert passt möglicherweise nicht, daher erzwingt Java einen expliziten Cast und verwirft stillschweigend, was nicht passt. Es wird abgeschnitten, nicht gerundet:
double d = 9.99;
int i = (int) d; // 9 — the fraction is dropped, never rounded
long big = 9_000_000_000L;
int truncated = (int) big; // 410065408 — high bits lost, value is garbageDaher solltest du nur dann einengen, wenn du sicher bist, dass der Wert passt. Um ein double auf die nächste ganze Zahl zu runden statt abzuschneiden, verwende Math.round (siehe Java Math).
Konvertierungen finden auch innerhalb von Ausdrücken statt. Die ganzzahlige Division verwirft den Rest, was Anfänger überrascht:
System.out.println(7 / 2); // 3 — both operands are int, so int division
System.out.println(7 / 2.0); // 3.5 — one double operand promotes the whole expressionDie vollständigen Regeln für explizite Casts findest du unter Java Type Casting.
Überlauf
Ganzzahl-Arithmetik läuft still um die Grenzen des Typs herum. Es wird keine Ausnahme ausgelöst:
int max = Integer.MAX_VALUE;
System.out.println(max + 1); // -2147483648 (Integer.MIN_VALUE)Für überlaufgeprüfte Arithmetik verwende die Math.exact-Familie:
Math.addExact(Integer.MAX_VALUE, 1); // throws ArithmeticException
Math.multiplyExact(100_000, 100_000); // throws tooNützlich, wenn Korrektheit wichtiger ist als Leistung — Finanzberechnungen, Allokationsgrößen usw.
Gleitkomma-Präzision
double und float sind IEEE 754 binär — sie können die meisten Dezimalbrüche nicht exakt darstellen:
System.out.println(0.1 + 0.2); // 0.30000000000000004Vergleiche Gleitkommazahlen niemals mit ==. Vergleiche innerhalb einer Toleranz:
double diff = Math.abs(a - b);
if (diff < 1e-9) { /* close enough */ }Für Geldbeträge oder überall dort, wo du exakte Dezimalarithmetik benötigst, verwende BigDecimal:
import java.math.BigDecimal;
BigDecimal sum = new BigDecimal("0.1").add(new BigDecimal("0.2"));
System.out.println(sum); // 0.3Übergebe immer Strings an new BigDecimal(...). Der double-Konstruktor würde die binäre Ungenauigkeit wieder einführen.
Besondere Gleitkomma-Werte
double hat drei Werte, die keine gewöhnlichen Zahlen sind:
double posInf = Double.POSITIVE_INFINITY;
double negInf = Double.NEGATIVE_INFINITY;
double nan = Double.NaN;
System.out.println(1.0 / 0); // Infinity
System.out.println(-1.0 / 0); // -Infinity
System.out.println(0.0 / 0); // NaN
System.out.println(nan == nan); // false — NaN compares unequal to everything
System.out.println(Double.isNaN(nan)); // trueVerwende Double.isNaN(x), um auf NaN zu prüfen; == funktioniert nicht.
Die Wrapper-Klassen
Jeder Primitiv hat eine entsprechende Wrapper-Klasse: Byte, Short, Integer, Long, Float, Double. Die Wrapper erweitern die abstrakte Klasse Number. Du benötigst sie, wenn:
- Du Collections verwendest, die Objekte enthalten:
List<Integer>,Map<String, Double>. - Du aus Strings parsierst:
Integer.parseInt("42"),Double.parseDouble("3.14"). - Du über
.intValue(),.doubleValue()usw. in einen anderen numerischen Typ konvertierst.
Java führt automatisch Autoboxing zwischen Primitiv und Wrapper durch:
List<Integer> ids = new ArrayList<>();
ids.add(42); // autobox: int → Integer
int first = ids.get(0); // unbox: Integer → intBigInteger und BigDecimal
Wenn Zahlen größer als long sein können oder du Dezimalpräzision benötigst:
import java.math.BigInteger;
BigInteger huge = new BigInteger("123456789012345678901234567890");
huge.multiply(huge);
BigDecimal price = new BigDecimal("19.95");
BigDecimal tax = price.multiply(new BigDecimal("0.07"));Sie sind langsamer als Primitive, aber für die Fälle, in denen sie benötigt werden, ist das der richtige Kompromiss.
Eine Demonstration
Was kommt als Nächstes
- Java Math —
Math.abs,Math.round,Math.powund der Rest des numerischen Werkzeugkastens. - Java Operators — wie sich Arithmetik-, Vergleichs- und bitweise Operatoren auf diese Typen verhalten.
- Java Booleans — Javas zweiweriger Typ, mit viel weniger Details.