Primitive Datentypen – Python und Java im Vergleich
“Primitve” Datentypen sind “unboxed” Typen “nicht primitiven” Datentypen sind “gepackte” also “boxed” Typen. Der Unterschied liegt darin, wie die Werte der Variablen im Memory dargestellt werden. Holen wir aus:
Primitive Datentypen und 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.
Fü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.
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.