Veröffentlicht am

Primitive Datentypen

Primitive Datentypen

Primitive Datentypen – Python und Java im Vergleich

Wenn es primitive Datentypen gibt, welche sind dann die “nicht primitiven” Datentypen?

Antwort: “primitve” Datentypen sind “unboxed” Typen “nicht primitiven” Datentypen sind “gepackte” also “boxed” Typen.  Nicht wirklich hilfreich, nicht wahr?   Holen wir aus:

Autorin: Ursula Deriu

Objektorientierte Sprachen

Die Unterscheidung in die zwei Arten Datentypen ist in objektorientierten Sprachen sinnvoll.

Nehmen wir Java als Beispiel einer objektorientierten Sprache. Auch Python gehört zu dieser Sprachfamilie.

Der Unterschied zwischen diesen zwei Sprachen hinsichtlich Datentypen: Java ist typsicher – Python ist es nicht.

Wie äußert sich das?

Typsicher oder nicht typsicher?

In Java sagen wir

int javaZahl = 1;

Und in Python sagen wir:

python_zahl = 1

Der Python-Interpreter analysiert den Kontext, stellt fest, dass rechts vom Zuweisungszeichen eine konstante ganze Zahl steht und leitet daraus ab, dass python_zahl auch eine ganze Zahl sein muss, also ein int.

In Java, als typsichere Sprache, geben wir bei der Definition der Variablen bekannt, welchen Datentyp wir wünschen.

Und da bemerken wir in Java den Unterschied zwischen primitiven Datentypen und unboxed Datentypen.

In Java sagen wir beispielsweise:

ArrayList javaListe = new ArrayList();

Der Unterschied zur Definition einer Variablen mit primitivem Datentyp sticht ins Auge.

In Python sagen wir:

python_liste = []

Und damit definieren wir eine leere Liste.

In Python sind alle Datentypen “boxed” – Python kennt also gar keine primitiven Datentypen.

Java macht die Unterscheidung.

Konzentrieren wir uns also auf Java.

Wollen wir eine ganzzahlige Variable definieren, dann haben wir auch in Java zwei Möglichkeiten:

int primitiverInt = 1;

oder

Integer classInt = 1;

Im zweiten Fall könnten wir auch schreiben:

Integer classInt = new Integer(1);

Hier sieht man schön, wie der primitive Typ, dargestellt durch die 1, eingepackt wird – also in eine Box verpackt. Der primitve Typ, steht allein, ohne diese Box und ist “unboxed”.

Diese zweite Definitionsweise war in früheren Java-Versionen für Wrapper-Klassen obligatorisch und wurde inzwischen vereinfacht.

Und welches ist jetzt der Unterschied zwischen den beiden Arten ganzer Zahlen?

Dazu müssen wir verstehen, wie die Daten im Memory dargestellt werden.

Hier eine vereinfachte Darstellung:

Datentypen im Memory

Daten belegen Zellen im Memory. Wir schreiben “Zellen” um jetzt nicht noch zu erläutern, was Bytes genau sind. Die Zellen sind adressiert, also durchnummeriert.

Primitive Datentypen im RAMFür int wissen wir, dass Java 32 Bit Platz benötigt. Also 32 mal den Platz für eine 0 oder 1. Auch hier kürzen wir ab und erklären nicht, wie das genau geht.

Diese 32 Bit haben eine Adresse. Diese wird zur Laufzeit des Programms zugewiesen und zwar zum Zeitpunkt der Definition der jeweiligen Variablen, also beispielsweise primitiverInt.

Zur Laufzeit des Programms wird dann jedes Mal, wenn mit primitiverInt gerechnet wird, diese Adresse verwendet, um den aktuellen Wert der Variablen zu finden.

Statt “Adresse” sagt man auch “Zeiger”, englisch: “Pointer”. Weil die Adresse ja auf eine Stelle im Memory “zeigt”.

Und so spricht man auch von Random Access Memory, RAM. Die Adressen können aus dem Programm heraus auf beliebige Stellen im Memory zeigen. Welche es sind, bestimmt das Programm zur Laufzeit.

Das siehst du im Bild: Hier wurde zur Laufzeit die Adresse 1001 ermittelt und dort wird der Wert von primitiverInt gespeichert. Bei der nächsten Ausführung des Programms wird es eine andere Adresse sein.

Anders bei classInt

Da wird zur Laufzeit des Programms zum Zeitpunkt der Definition der Variablen classInt ein zweistufiger Prozess durchlaufen. Dieser ist im Bild illustriert:

Zuerst wird eine Adresse im Memory ermittelt – so wie auch bei primitiverInt. Im Bild ist das 1004. Doch an dieser Adresse steht nicht direkt der Wert der Variablen, sondern eine weitere Adresse. Im Bild ist das 1006. Und diese Adresse verweist auf eine weitere Stelle im Memory, auf der der eigentliche Wert der Variablen classInt steht.

Du findest, das sei unnötig kompliziert?

Da hast du möglicherweise recht. Doch die Vorteile sind enorm:

Vorteile primitiver Datentypen

Illustrieren wir das anhand des Unterschieds zwischen ganzen Zahlen in Python und Java

int in Java belegt 32 Bit. Reichen diese 32 Bit nicht aus, um den Wert der Zahl darzustellen, dann wirft Java eine Fehlermeldung.

Nicht so Python. Dort wird int als eine objektorientierte Klasse implementiert. Auch hier wird Python-Interpreter zur Laufzeit für die Variable eine Speicheradresse festlegen. Im Bild könnte das beispielsweise 1004 sein.

Und an der Stelle dieser Adresse steht eine weitere Adresse zu dem Bereich im Memory, der den Wert der Variablen darstellt. Im Bild ist das 1006.

Dort ist auch Platz für den Wert der Zahl reserviert.

Doch anders als in Java, brauchen wir uns in Python nicht um diesen Platz zu kümmern. Python sorgt dafür, dass der Platz automatisch erweitert wird, wenn die Zahl zu groß wird:

In dem Fall reserviert Python an anderer Stelle noch mehr Platz, im Bild könnte das an Adresse 1002 sein und dort wird gleich auch 1003 mit reserviert.

Python ändert die Adresse an Stelle 1004 ab – neu wird sie 1002. Python merkt sich auch, dass zwei Zellen reserviert sind, also 1002 und 1003.

Die Adresse, die das Programm benötigt, um die Variable darzustellen, bleibt bestehen – also 1004.

  • Klick aufs Bild und hol dir das kostenlose Cheat Sheet Wichtigste Python-Datentypen

Platz im Memory dynamisch verwalten

Ein cleverer Trick, den sich die Leute haben einfallen lassen, die Objektorientierung erfunden haben. So können Klassen geschrieben werden, mit denen dynamisch viel Platz im Memory verwendet wird.

Java kann das auch, beispielsweise mit ArrayList. Gleich wie in Python kann auch in Java die Anzahl der Listenelemente dynamisch, also während der Laufzeit des Programms, geändert werden.

Der Java-Datentyp Integer ist leider nicht so schlau, wie sein Pendant in Python.

In Java können wir verschiedene ganze Zahlen haben: byte, short, int long – das sind alles primitive Datentypen für ganze Zahlen. Wir müssen uns darum kümmern, dass die Anzahl Bits, die sie repräsentieren, für unsere Werte ausreichen. Auch die entsprechenden Wrapper-Klassen (so heißen sie) Byte, Short, Integer, Long, sind nur Attrappen – im Herzen haben sie den jeweiligen primitiven Datentyp und bieten nicht die Flexibilität von Python.

Die Java-Spracharchitekten könnten sich entscheiden, das zu ändern – haben es aber nicht vor.

Und ja – es gibt noch mehr primitive Datentypen in Java:

float und double für Zahlen mit Nachkommastellen

boolean für true-false Variable

char für einzelne Buchstaben.

Fazit

Primitive Datentypen gibt es nicht in allen Programmiersprachen. Objektorientierte Programmiersprachen können primitive Datentypen anbieten – müssen aber nicht.

Python ist enorm flexibel bei der Handhabung von Zahlen. Darum ist die Sprache für Datenanalysen auch so beliebt.