Java-Datentypen erklärt: Primitive vs Referenztypen, Casting und Wrapper-Klassen

目次

1. Was sind Java-Datentypen? Grundlagen und der große Überblick

Java-Datentypen sind ein Mechanismus, der bestimmt, welche Art von Wert eine Variable speichern kann.
Java legt großen Wert auf Typsicherheit (ein Design, das ungültige Typoperationen zur Kompilierzeit verhindert), daher muss jede Variable einen deklarierten Typ haben.

Zum Beispiel schauen Sie sich den folgenden Code an.

int number = 10;
double price = 19.8;
String name = "Java";
  • int → nur Ganzzahlen
  • double → nur Dezimalzahlen
  • String → nur Strings

Durch die explizite Angabe von Typen erhalten Sie Vorteile wie:

  • Verhindert ungültige Zuweisungen
  • Optimiert den Speicherverbrauch
  • Erfasst Fehler zur Kompilierzeit

Wenn es keine Typen gäbe, würden Fehler wie die Zuweisung eines Strings zu einer Ganzzahl nicht bis zur Laufzeit entdeckt. Java ist so konzipiert, dass dies verhindert wird.

1.1 Was ist ein Datentyp? (Anfängerfreundliche Definition)

Denken Sie an einen Datentyp als „die Art von Werten, die eine Variable handhaben darf.“

Die grundlegende Syntax ist:

TypeName variableName = value;

Beispiel:

int age = 25;

In diesem Fall:

  • int ist der Typ
  • age ist der Variablenname
  • 25 ist der Wert

Das ist die Beziehung.

Wenn Sie das schreiben, erhalten Sie einen Fehler:

int age = "25";  // Compile-time error

Sie können keinen String einem Ganzzahltyp zuweisen. So funktioniert Typsicherheit.

Häufige Anfängerfehler

  • Annehmen, dass Typen weggelassen werden können (in Java im Allgemeinen nicht)
  • Verwechslung von Zahlen und Strings
  • Verwechslung von = (Zuweisung) und == (Vergleich)

1.2 Kategorien von Java-Datentypen (Zwei Typen)

Java-Datentypen werden grob in zwei Kategorien unterteilt:

  1. Primitive Typen
  2. Referenztypen

Was sind primitive Typen?

Typen, die den tatsächlichen Wert direkt speichern.
Beispiele: int, double, boolean usw.

Eigenschaften:

  • Speichereffizient
  • Schnell
  • Können null nicht halten

Was sind Referenztypen?

Typen, die nicht den Wert selbst speichern, sondern eine „Referenz“ darauf, wo der Wert gespeichert ist.

Beispiel:

String text = "Hello";

String ist ein Klassentyp (ein Referenztyp).

Eigenschaften:

  • Basierend auf Klassen erstellt
  • Können null zugewiesen werden
  • Haben Methoden (Verhalten)

1.3 Der Unterschied im Verhalten von „Wert vs. Referenz“

Lassen Sie uns den Unterschied mit einem einfachen Beispiel bestätigen.

int a = 10;
int b = a;
b = 20;

In diesem Fall:

  • a bleibt 10
  • Nur b wird 20

Andererseits funktionieren Referenztypen so:

String s1 = "Java";
String s2 = s1;

Hier können s1 und s2 dasselbe Objekt referenzieren (das kann je nach Implementierung und Optimierungen variieren).

Häufige Stolpersteine

  • Missverständnis von String als primitiven Typ
  • Annehmen, dass das Kopieren eines Referenztyps den Wert selbst kopiert
  • Nicht verstehen, wie null funktioniert

1.4 Warum das Verständnis von Datentypen wichtig ist

Ein schlechtes Verständnis von Datentypen kann Probleme wie folgende verursachen:

  • Unerwartete Rechenergebnisse
  • Überlauf (Überschreitung des Wertebereichs)
  • NullPointerException
  • Typkonvertierungsfehler

Um Java korrekt zu verwenden, müssen Sie zuerst das Gesamtbild der Datentypen verstehen.

2. Primitive Typen (Grundlegende Datentypen): Liste und Verwendung

Primitive Typen sind Datentypen, die den tatsächlichen Wert direkt speichern.
Java hat 8 primitive Typen.

CategoryTypeSizeTypical Use
Integerbyte8bitSmall integers
Integershort16bitSmaller integers
Integerint32bitStandard integers
Integerlong64bitLarge integers
Decimalfloat32bitSingle-precision floating point
Decimaldouble64bitDouble-precision floating point (standard)
Characterchar16bitA single character
Booleanbooleantrue / false

*Größen sind durch die Java-Spezifikation festgelegt (nicht umgebungabhängig).

2.1 Ganzzahltypen (byte / short / int / long)

Grundlegende Verwendung

int number = 100;
long population = 8000000000L;

Bereiche (häufige Beispiele)

  • byte: -128 bis 127
  • short: -32.768 bis 32.767
  • int: ca. ±2,1 Milliarden
  • long: ca. ±9,22 Quintillionen

In den meisten Fällen reicht int aus.
Es gibt selten einen praktischen Bedarf, byte oder short nur um Speicher zu sparen zu verwenden.

Wichtiger Hinweis bei der Verwendung von long

long value = 10000000000L;  // L is required

Ohne das L wird der Literal als int behandelt und kann einen Kompilierungsfehler aufgrund von Out-of-Range verursachen.

Häufige Fehler

  • Überlauf durch Überschreiten des Bereichs
  • Vergessen von L für long-Literale
  • Überlauf bei int-zu-int-Berechnungen nicht bemerkt

2.2 Gleitkommatypen (float / double)

double price = 19.99;
float rate = 0.5f;

Grundregeln

  • In der Regel double verwenden
  • float erfordert ein nachgestelltes f
    float value = 3.14f;
    

Unterschiedliche Genauigkeiten

  • float: etwa 7 Stellen Genauigkeit
  • double: etwa 15 Stellen Genauigkeit

Wichtiger Hinweis (Rundungs-/Genauigkeitsprobleme)

System.out.println(0.1 + 0.2);

Das Ergebnis ist möglicherweise nicht exakt 0,3.
Dies liegt an der binären Gleitkommadarstellung.

Geldberechnungen

Für Geldberechnungen wird double im Allgemeinen nicht empfohlen.
Die Verwendung von BigDecimal ist sicherer.

Häufige Fehler

  • double für Geld verwenden
  • float und double verwechseln
  • Dezimalzahlen mit == vergleichen

2.3 Zeichentyp (char)

char letter = 'A';
  • Verwendet einfache Anführungszeichen
  • Verwaltet mit Unicode (ein Zeichenkodierungsstandard)
  • Kann nur ein einzelnes Zeichen speichern
    char kanji = '日';
    

Häufige Fehler

  • Doppelte Anführungszeichen verwenden (das ist String )
  • Versuch, mehrere Zeichen zu speichern

2.4 Boolescher Typ (boolean)

boolean isActive = true;
  • Werte sind nur true oder false
  • Sie können nicht 0/1 verwenden (anders als in C)
    boolean result = (5 > 3);
    

Häufige Fehler

  • Versuch, eine Zahl zuzuweisen
  • Vergessen, den Vergleichsausdruck zu schreiben

2.5 Allgemeine Hinweise zu primitiven Typen

  • Sie können nicht null zuweisen
  • Standardwerte werden für Felder automatisch gesetzt, lokale Variablen müssen jedoch initialisiert werden
    int x;
    System.out.println(x);  // Compile-time error (uninitialized)
    

Primitive Typen sind schnell und leichtgewichtig, haben jedoch Einschränkungen, wie das Fehlen von null-Unterstützung und das Fehlen von Methoden.

3. Referenztypen: Grundlagen

Referenztypen speichern nicht den Wert selbst, sondern eine Referenz (Speicheradresse) auf ein Objekt.
Der größte Unterschied zu primitiven Typen besteht darin, dass „die Daten selbst“ und die „Variable“ getrennt existieren.

Betrachten Sie dieses Beispiel:

String text = "Java";

Hier speichert text eine Referenz auf das String-Objekt, nicht den String-Wert selbst.

3.1 String-Typ (Der am häufigsten verwendete Referenztyp)

String ist ein Klassentyp. Es ist kein primitiver Typ.

String name = "Taro";

Eigenschaften

  • Unveränderlich (kann nicht geändert werden)
  • Kann null zugewiesen werden
  • Hat Methoden
    String str = "Hello";
    System.out.println(str.length());  // 5
    

Falle der Unveränderlichkeit

String s = "Java";
s.concat(" SE");
System.out.println(s);  // "Java"

concat() gibt einen neuen String zurück, aber der ursprüngliche String wird nicht verändert.

Korrekte Verwendung:

s = s.concat(" SE");

Häufige Fehler

  • Annehmen, dass String ein primitiver Typ ist
  • == für den String-Vergleich verwenden
  • Aufwändige Verkettungen verursachen Leistungsprobleme (verwenden Sie StringBuilder)

3.2 Arrays und Klassentypen

Arrays

int[] numbers = {1, 2, 3};

Arrays sind ebenfalls Referenztypen.

int[] a = {1, 2};
int[] b = a;
b[0] = 99;

System.out.println(a[0]);  // 99

Da a und b auf dasselbe Array verweisen, wirken sich Änderungen auf beide aus.

Klassentypen

class Person {
    String name;
}

Person p = new Person();
p.name = "Ken";

new ist das Schlüsselwort zum Erzeugen eines Objekts.

3.3 Was ist null?

null steht für einen Zustand, in dem „kein referenziertes Objekt existiert“.

String text = null;

Ein Aufruf einer Methode, wenn eine Referenz null ist, verursacht einen Fehler.

text.length();  // NullPointerException

Dies wird als NullPointerException (NPE) bezeichnet.

Wie man mit null umgeht

if (text != null) {
    System.out.println(text.length());
}

3.4 Der Unterschied zwischen == und equals()

== (Referenzvergleich)

Vergleicht, ob die Speicheradressen identisch sind.

equals() (Inhaltsvergleich)

Vergleicht, ob die Inhalte gleich sind.

String a = new String("Java");
String b = new String("Java");

System.out.println(a == b);        // false
System.out.println(a.equals(b));   // true

Häufige Fehler

  • Verwendung von == zum Vergleich von Zeichenketten
  • equals() aufrufen, ohne auf null zu prüfen
  • Verwechseln von Referenzkopien und Wertkopien

3.5 Kurze Zusammenfassung: Unterschiede zu primitiven Typen

ItemPrimitive TypesReference Types
StoresThe value itselfA reference
nullNot allowedAllowed
MethodsNoYes
newNot neededUsually needed

Referenztypen sind flexibel, aber man muss beim Umgang mit null und geteilten Referenzen vorsichtig sein.

4. Wrapper‑Klassen und Autoboxing

Wrapper‑Klassen sind Klassen, die es ermöglichen, primitive Werte wie Objekte zu behandeln.
In Java können Sammlungen (wie List und Map) nur Referenztypen speichern, sodass primitive Typen nicht direkt gespeichert werden können. Wrapper‑Klassen gibt es zu diesem Zweck.

4.1 Häufige Wrapper‑Klassen

Primitive TypeWrapper Class
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean

Beispiel:

Integer number = 10;
Double price = 19.99;

Da Wrapper‑Klassen Referenztypen sind, können sie null enthalten.

Integer value = null;  // OK

4.2 Was ist Autoboxing?

Boxing bedeutet, einen primitiven Typ in eine Wrapper‑Klasse zu konvertieren.

Seit Java 5 kann diese Konvertierung automatisch erfolgen.

Integer num = 10;  // autoboxing

Intern entspricht das:

Integer num = Integer.valueOf(10);

4.3 Was ist Unboxing?

Unboxing konvertiert eine Wrapper‑Klasse zurück in einen primitiven Typ.

Integer num = 20;
int value = num;  // auto-unboxing

Intern:

int value = num.intValue();

4.4 Wann Sie Wrapper‑Klassen benötigen

1. Beim Einsatz von Sammlungen

import java.util.ArrayList;

ArrayList<Integer> list = new ArrayList<>();
list.add(10);  // autoboxing

Sie können ArrayList<int> nicht verwenden.

2. Wenn Sie null behandeln müssen

Integer score = null;

Primitive Typen können nicht null sein.

4.5 Hinweise und häufige Fehler

1. Ausnahme beim Unboxing von null

Integer num = null;
int value = num;  // NullPointerException

Während des automatischen Unboxings tritt eine Ausnahme auf.

2. Vergleich mit ==

Integer a = 1000;
Integer b = 1000;

System.out.println(a == b);  // may be false

Da es sich um Objekte handelt, vergleicht == Referenzen.
Verwenden Sie equals() für den Inhaltsvergleich.

a.equals(b);

3. Leistungseinfluss

Wrapper‑Klassen können die Objekterstellung erfordern, sodass rechenintensive Vorgänge langsamer sein können als bei Verwendung primitiver Typen.

4.6 Auswahl zwischen primitiven Typen und Wrapper‑Klassen

  • Numerische Berechnungen → primitive Typen
  • Speicherung in Sammlungen → Wrapper‑Klassen
  • Umgang mit null → Wrapper‑Klassen

Wenn Sie diese Richtlinien beachten, zögern Sie in der Praxis nicht.

5. Typumwandlung (Casting): Grundlagen

In Java verwendet man Typumwandlung (Casting), wenn man mit Werten verschiedener Datentypen arbeitet.
Es gibt zwei Hauptarten:

  • Implizite Umwandlung (Widening‑Umwandlung)
  • Explizite Umwandlung (Narrowing‑Umwandlung)

5.1 Implizite Umwandlung (Widening)

Umwandlungen von einem Typ mit kleinerem Wertebereich zu einem Typ mit größerem Wertebereich erfolgen automatisch.

int num = 100;
long bigNum = num;  // automatic conversion

Das ist sicher, weil der Zahlenbereich erweitert wird.

Umwandlungsreihenfolge (Beispiel für Ganzzahlen)

byte → short → int → long → float → double

Beispiel

int a = 10;
double b = a;  // OK

Hinweise

  • Die Genauigkeit bleibt in vielen Fällen erhalten, jedoch kann bei float oder double eine Rundung auftreten.
  • char kann als ganzzahliger Wert konvertiert werden.
    char c = 'A';
    int code = c;  // 65
    

5.2 Explizite Umwandlung (Narrowing)

Bei der Umwandlung von einem größeren zu einem kleineren Typ muss explizit gecastet werden.

double price = 19.99;
int rounded = (int) price;

Das Ergebnis ist:

rounded = 19

Der Nachkommanteil wird abgeschnitten.

Syntax

(TargetType) variable

5.3 Beispiel für Datenverlust

int big = 1000;
byte small = (byte) big;
System.out.println(small);

Das Ergebnis ist nicht „unvorhersehbar“, sondern auf den Zielbereich begrenzt.
Hier überschreitet 1000 den byte‑Bereich, sodass sich der Wert ändert.

Häufige Missverständnisse

  • Denken, dass es einen Fehler verursacht → in Wirklichkeit ändert sich der Wert
  • Annehmen, dass es immer sicher ist → Datenverlust kann auftreten

5.4 Eine Stolperfalle: Ganzzahlige Division

int a = 5;
int b = 2;
double result = a / b;
System.out.println(result);

Das Ergebnis ist:

2.0

Ganzzahlige Division wird als ganzzahlige Operation ausgeführt.

Korrekte Vorgehensweise:

double result = (double) a / b;

Ergebnis:

2.5

5.5 Hinweise zum Vergleich von Dezimalzahlen

double x = 0.1 + 0.2;
System.out.println(x == 0.3);  // may be false

Dies liegt an Problemen mit der Gleitkommapräzision.

Ein sichererer Vergleich

Math.abs(x - 0.3) < 0.000001

5.6 Typumwandlung von Referenztypen

Sie können auch Referenztypen umwandeln (wenn eine Vererbungsbeziehung besteht).

Object obj = "Java";
String str = (String) obj;

Die Umwandlung in einen falschen Typ verursacht eine Ausnahme.

Integer num = (Integer) obj;  // ClassCastException

Zusammenfassung häufiger Fehler

  • Konvertierungen außerhalb des Bereichs ändern Werte
  • Ganzzahlige Division nicht bemerken
  • Dezimalzahlen mit == vergleichen
  • Ungültige Referenzumwandlungen erzwingen

Umwandlungen lösen oft keinen Kompilierfehler aus, sodass Missverständnisse leicht zu Bugs führen.

6. Ein praktischer Leitfaden zur Typauswahl (damit Sie bei der Arbeit nicht zögern)

Jetzt, wo Sie verstehen, wie Java‑Datentypen funktionieren, lautet eine häufige Praxisfrage: „Welchen Typ soll ich verwenden?“ Dieser Abschnitt ordnet praktische Entscheidungskriterien.

6.1 Warum int und double in der Regel ausreichen

Verwenden Sie int für Ganzzahlen (standardmäßig)

int count = 100;

Gründe:

  • Der 32‑Bit‑Bereich ist für die meisten Fälle ausreichend
  • Für die JVM leichter zu optimieren
  • Lesbar und standardisiert

Sie müssen byte oder short in der Regel nicht erzwingen.
Kleinere Typen nur zum Speichern von Speicherplatz zu wählen, ist meist nur für Sonderfälle (wie riesige Arrays) sinnvoll.

Verwenden Sie double für Dezimalzahlen (standardmäßig)

double rate = 0.75;

Es hat höhere Präzision als float und ist die Standardwahl.
Sofern Sie keinen klaren Grund haben, wählen Sie double.

6.2 Warum Sie BigDecimal für Geldbeträge verwenden sollten

Dieser Code ist riskant für Geld:

double price = 0.1 + 0.2;

Aufgrund von Gleitkomma‑Fehlern erhalten Sie möglicherweise keinen exakten Wert.

Korrekte Vorgehensweise:

import java.math.BigDecimal;

BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal result = a.add(b);

Warum Zeichenketten übergeben?

new BigDecimal(0.1);  // not recommended

Die Erstellung aus einem double kann dessen Präzisionsfehler übernehmen.

Häufige Fehler

  • Geld mit double verarbeiten
  • Verwendung von new BigDecimal(doubleValue)
  • Vergessen von Rundungsregeln

6.3 Sammlungen erfordern Wrapper‑Klassen

import java.util.ArrayList;

ArrayList<Integer> list = new ArrayList<>();
list.add(10);

Sie können primitive Typen nicht direkt verwenden.

ArrayList<int> list;  // Compile-time error

Grund:

  • Generics (typsichere Sammlungen) unterstützen nur Referenztypen

6.4 Entscheiden Sie basierend darauf, ob Sie null benötigen

Kein null benötigt → primitive Typen

int age = 0;

null benötigt → Wrapper‑Klassen

Integer age = null;

Bei Datenbankintegrationen oder Formulareingaben benötigen Sie möglicherweise die Behandlung von null.

6.5 Grundlegende Leistungsrichtlinien

  • Berechnungen → primitive Typen
  • Sammlungen → Wrapper‑Klassen
  • Vermeiden Sie das Erstellen von Wrappern in engen Schleifen

Beispiel (nicht empfohlen):

for (Integer i = 0; i < 1000000; i++) { }

Die Verwendung primitiver Typen ist effizienter.

6.6 Zusammenfassungstabelle: Empfohlene Typen nach Anwendungsfall

Use CaseRecommended Type
Typical integersint
Typical decimalsdouble
MoneyBigDecimal
Boolean checksboolean
StringsString
Storing in collectionsWrapper classes

Häufige Fehler in der Praxis

  • Unnötig kleine Typen wählen
  • double für Geld verwenden
  • Ohne Berücksichtigung von null entwerfen
  • Auto‑Unboxing‑Ausnahmen von Wrapper‑Klassen

Die Auswahl von Typen ist ein zentraler Bestandteil des Designs. Wenn man mit Unklarheiten fortfährt, steigen die Kosten für die spätere Behebung von Problemen erheblich.

7. Zusammenfassung der Java-Datentypen (mit Tabellen)

Fassen wir alles in einem Format zusammen, das häufige Suchanfragen schnell beantwortet.
Java‑Datentypen werden in „primitive Typen“ und „Referenztypen“ unterteilt.

7.1 Liste der primitiven Typen

TypeSizeDefault (fields)Typical Use
byte8bit0Small integers
short16bit0Smaller integers
int32bit0Standard integers
long64bit0LLarge integers
float32bit0.0fSingle-precision floating point
double64bit0.0dStandard floating point
char16bit‚\u0000‘A single character
booleanfalseBoolean value

*Lokale Variablen werden nicht automatisch initialisiert.

Wichtige Punkte

  • Für numerische Berechnungen standardmäßig int / double verwenden
  • Für Geld BigDecimal verwenden
  • null ist nicht erlaubt
  • Keine Methoden

7.2 Überblick über Referenztypen

Typische Referenztypen:

  • String
  • Arrays (z. B. int[] )
  • Klassentypen (benutzerdefinierte Klassen)
  • Wrapper‑Klassen (z. B. Integer )
  • Collections (List, Map usw.)

Zusammenfassung der Eigenschaften

ItemReference Types
Can assign nullYes
MethodsAvailable
new keywordUsually needed
Comparisonequals() recommended

7.3 Endvergleich: Primitive vs. Referenz

PerspectivePrimitive TypesReference Types
StoresDirectlyBy reference
Memory efficiencyHighSomewhat lower
nullNoYes
SpeedFastSomewhat slower
Main useCalculationsObject handling

7.4 Das minimale Set, das Anfänger zuerst lernen sollten

Beginnen Sie mit diesen vier Typen:

  • int
  • double
  • String
  • boolean

Damit können Sie grundlegende Programme erstellen.

7.5 Häufige allgemeine Fehler

  1. String mit == vergleichen
  2. double für Geld verwenden
  3. Ganzzahlige Division übersehen
  4. null‑Prüfungen vergessen
  5. Das L für long‑Literale vergessen
  6. null beim Unboxing in Wrapper‑Klassen

Allein das Vermeiden dieser Fehler reduziert Anfängerfehler erheblich.

7.6 Abschließende Erkenntnisse

  • Java ist eine typensichere Sprache
  • Das Verständnis von Datentypen ist die Grundlage allen Codes
  • Primitive Typen dienen schnellen Berechnungen
  • Referenztypen dienen der Verwaltung von Objekten
  • Die Wahl des richtigen Typs beeinflusst die Qualität direkt

FAQ

Q1. Wie viele Java‑Datentypen gibt es?

Antwort:
Es gibt 8 primitive Typen. Referenztypen können unzählig sein (Klassen, Arrays, Schnittstellen usw.). Es ist wichtig, zuerst die 8 primitiven Typen zu verstehen.

Q2. Ist String ein primitiver Typ?

Antwort:
Nein. String ist ein Klassentyp (ein Referenztyp). Er wird als Objekt behandelt und kann null zugewiesen bekommen.

Q3. Was ist der Unterschied zwischen int und Integer?

Antwort:
int ist ein primitiver Typ. Integer ist eine Wrapper‑Klasse (ein Referenztyp). Integer kann null enthalten, aber Auto‑Unboxing kann eine Ausnahme auslösen.

Q4. Kann ich double für Geldberechnungen verwenden?

Antwort:
Technisch ja, aber es wird nicht empfohlen. Probleme mit der Gleitkommapräzision können auftreten, daher ist die Verwendung von BigDecimal sicherer.

Q5. Warum erzeugt die Division von Ganzzahlen keinen Dezimalwert?

Antwort:
Weil Ganzzahloperationen mit Ganzzahltypen durchgeführt werden, wird der Bruchteil abgeschnitten. Wenn Sie ein Dezimalergebnis benötigen, casten Sie einen Operanden zu double.

Q6. Was ist null?

Antwort:
Es stellt einen Zustand dar, in dem kein Objekt referenziert wird. Das Aufrufen einer Methode auf null führt zu einer NullPointerException.

Q7. Was ist der Unterschied zwischen == und equals()?

Antwort:
== vergleicht Referenzen (Speicheradressen). equals() vergleicht Inhalte. Für den String‑Vergleich verwenden Sie equals().

Q8. Welche Typen sollten Anfänger zuerst lernen?

Antwort:
Priorisieren Sie int, double, String und boolean. Dies sind die am häufigsten verwendeten Kerntypen in der Praxis.