1. Alle Klassen erbenObject
Alle Klassen in Java erben implizit die Object
Klasse.
Wir werden in der Java Core-Quest analysieren, was Vererbung ist und wie sie in Java funktioniert. Zunächst betrachten wir eine einfache Tatsache, die sich daraus ergibt:
Einer Variablen kann ein Objekt einer beliebigen Klasse zugewiesen werden Object
. Beispiel:
Code | Notiz |
---|---|
|
Die o Variable speichert einen Verweis auf ein Scanner Objekt |
|
Die o Variable speichert einen Verweis auf ein String Objekt |
|
Die o Variable speichert einen Verweis auf ein Integer Objekt |
|
Die o Variable speichert einen Verweis auf ein String Objekt |
Hier endet die gute Nachricht. Der Compiler verfolgt den ursprünglichen Typ des in einer Object
Variablen gespeicherten Objekts nicht, sodass Sie keine anderen Methoden als die Methoden der Klasse für das gespeicherte Objekt aufrufen können .Object
Wenn Sie die mit dem ursprünglichen Typ des Objekts verknüpften Methoden aufrufen müssen, müssen Sie zunächst einen Verweis darauf in einer Variablen des richtigen Typs speichern und dann die Methoden für diese Variable aufrufen:
Code | Notiz |
---|---|
|
Das Programm lässt sich nicht kompilieren. Die Object Klasse hat keine nextInt() Methode. |
|
Das wird funktionieren. Hier speichern wir mithilfe eines Typumwandlungsoperators Scanner einen Verweis auf ein Objekt in einer Variablen . Scanner |
Object
Sie können einer Scannervariablen nicht einfach eine Variable zuweisen , selbst wenn die Object
Variable einen Verweis auf ein Scanner
Objekt speichert. Sie können dies jedoch tun, wenn Sie den Typecast-Operator verwenden , den Sie bereits kennen. Dies ist sein allgemeines Erscheinungsbild:
Type name1 = (Type) name2;
Dabei name1
ist der Name einer Type
Variablen und name2
der Name einer Object
Variablen, die einen Verweis auf ein Type
Objekt speichert.
Typisierung
Wenn der Typ der Variablen und der Typ des Objekts nicht übereinstimmen, ClassCastException
wird ein Fehler ausgelöst. Beispiel:
Code | Notiz |
---|---|
|
Zur Laufzeit tritt ein Fehler auf: Hier wird ein Fehler ausgelöst ClassCastException |
In Java gibt es eine Möglichkeit, diesen Fehler zu vermeiden: Wir überprüfen dazu den Typ des in einer Variablen gespeicherten Objekts :
name instanceof Type
Der instanceof
Operator prüft, ob die name
Variable ein Objekt ist Type
.
Lassen Sie uns als Beispiel eine Zeichenfolge in einem Array verschiedener Objekte finden:
Code | Notiz |
---|---|
|
Durch Autoboxing werden diese Werte jeweils in Integer , String und umgewandelt Double . Schleife über das Array von Objekten. Wenn es sich bei dem Objekt um ein Objekt handelt, String speichern Sie es in einer String Variablen . Zeigen Sie die Variable auf dem Bildschirm an. |
2. Warum Generika auftauchten – Sammlungen
Kehren wir zu den Sammlungen zurück.
Sobald Java-Entwickler die ArrayList
Klasse erstellt hatten, wollten sie sie universell machen, damit sie jede Art von Objekt speichern kann. Also verwendeten sie ein Array von Object
s, um die Elemente zu speichern.
Die Stärke dieses Ansatzes besteht darin, dass Sie der Sammlung ein Objekt beliebigen Typs hinzufügen können.
Natürlich gibt es mehrere Schwächen.
Nachteil 1.
Beim Abrufen von Elementen aus einer Sammlung war es immer notwendig, einen Typkonvertierungsoperator zu schreiben:
Code | Notiz |
---|---|
|
Erstellen Sie eine Sammlung, um Verweise auf Object Objekte zu speichern . Füllen Sie die Sammlung mit Zahlen 10 , 20 , ... 100 ; Summieren Sie die Elemente der Sammlung. Typecasting ist erforderlich |
Nachteil 2.
Es gab keine Garantie dafür, dass eine Sammlung einen bestimmten Elementtyp enthält
Code | Notiz |
---|---|
|
Erstellen Sie eine Sammlung, um Verweise auf Object Objekte zu speichern. Wir füllen die Sammlung mit Zahlen, die als Double Objekte dargestellt werden: 0.0 , 2.5 , 5.0 , ... Summieren Sie die Elemente der Sammlung . Es wird ein Fehler angezeigt: a Double kann nicht in an umgewandelt werdenInteger |
Daten können überall in die Sammlung aufgenommen werden:
- in einer anderen Methode
- in einem anderen Programm
- aus einer Datei
- über das Netzwerk
Nachteil 3.
Die Daten in der Sammlung können versehentlich geändert werden.
Sie können eine mit Ihren Daten gefüllte Sammlung an eine Methode übergeben. Diese von einem anderen Programmierer geschriebene Methode fügt ihre Daten Ihrer Sammlung hinzu.
Aus dem Namen der Sammlung geht nicht eindeutig hervor, welche Datentypen darin gespeichert werden können. Und selbst wenn Sie Ihrer Variablen einen eindeutigen Namen geben, kann ein Verweis darauf an ein Dutzend Methoden übergeben werden, und diese Methoden wissen definitiv nichts über den ursprünglichen Namen der Variablen.
3. Generika
In Java werden all diese Probleme durch diese coole Sache namens Generics beseitigt.
In Java bedeutet Generics die Möglichkeit, Typparameter zu Typen hinzuzufügen. Das Ergebnis ist ein komplexer zusammengesetzter Typ. Die allgemeine Ansicht eines solchen zusammengesetzten Typs ist folgende:
ClassName<TypeParameter>
Dies ist eine generische Klasse. Und es kann überall dort eingesetzt werden, wo Sie normalerweise Klassen verwenden.
Code | Beschreibung |
---|---|
|
Variablen erstellen |
|
Objekte erstellen |
|
Arrays erstellen |
Integer
In einer solchen Sammlung können nur Variablen gespeichert werden:
Code | Beschreibung |
---|---|
|
ArrayList Sammlung mit Integer Elementen Das ist erlaubt Und das wird auch funktionieren
Autoboxen
Dies ist jedoch nicht zulässig: Kompilierungsfehler |
In der Quest „Java-Sammlungen“ erfahren Sie, wie Sie Ihre eigenen Klassen mit Typparametern erstellen. Zunächst schauen wir uns an, wie man sie verwendet und wie sie funktionieren.
4. Wie Generika funktionieren
Eigentlich sind Generika furchtbar primitiv.
Der Compiler ersetzt einfach generische Typen durch gewöhnliche Typen. Wenn jedoch Methoden eines generischen Typs verwendet werden, fügt der Compiler einen Typecast-Operator hinzu, um Parameter in die Typparameter umzuwandeln:
Code | Was der Compiler macht |
---|---|
|
|
|
|
|
|
|
|
Angenommen, wir haben eine Methode, die die Zahlen in einer Sammlung von ganzen Zahlen summiert:
Code | Was der Compiler macht |
---|---|
|
|
Mit anderen Worten, Generika sind eine Art syntaktischer Zucker, genau wie Autoboxing, aber noch ein bisschen mehr. Beim Autoboxing fügt der Compiler Methoden zum Konvertieren von an int
in an Integer
und umgekehrt hinzu, und für Generika fügt er Typumwandlungsoperatoren hinzu.
Nachdem der Compiler Ihre generischen Klassen mit Typparametern kompiliert hat, werden sie einfach in gewöhnliche Klassen und Typumwandlungsoperatoren konvertiert. Informationen über die Typargumente, die an Variablen generischer Typen übergeben werden, gehen verloren. Dieser Effekt wird auch als Typlöschung bezeichnet .
Manchmal benötigen Programmierer, die generische Klassen (Klassen mit Typparametern) schreiben, wirklich Informationen über die als Argumente übergebenen Typen. In der Quest „Java-Sammlungen“ erfahren Sie, wie Sie damit umgehen und was es mit sich bringt.
5. Ein paar Fakten über Generika
Hier sind einige weitere interessante Fakten über Generika.
Klassen können mehrere Typparameter haben. Es sieht ungefähr so aus:
ClassName<TypeParameter1, TypeParameter2, TypeParameter3>
Eigentlich ist das nicht wirklich überraschend. Überall dort, wo der Compiler einen Operator zur Umwandlung in einen Typ hinzufügen kann, kann er mehrere Typumwandlungsoperatoren hinzufügen.
Beispiele:
Code | Notiz |
---|---|
|
Der put erste Parameter der Methode ist ein Integer und der zweite ist einString |
Als Parameter können auch generische Typen verwendet werden . Es sieht ungefähr so aus:
ClassName<TypeParameter<TypeParameterParameter>>
Angenommen, wir möchten eine Liste erstellen, die Listen mit Zeichenfolgen speichert. In diesem Fall erhalten wir etwa Folgendes:
// List of greetings
ArrayList<String> listHello = new ArrayList<String>();
listHello.add ("Hello");
listHello.add ("Hi");
// List of goodbyes
ArrayList<String> listBye = new ArrayList<String>();
listBye.add("Bye");
listBye.add ("Goodbye");
// List of lists
ArrayList<ArrayList<String>> lists = new ArrayList<ArrayList<String>>();
lists.add(listHello);
lists.add(listBye);
Generische Typen (Typen mit Typparametern) können auch als Array-Typen verwendet werden. Es sieht ungefähr so aus:
ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];
Hier passiert nichts Magisches: Die spitzen Klammern geben lediglich den Typnamen an:
Code | Nicht-generisches Gegenstück |
---|---|
|
|
|
|
|
|
GO TO FULL VERSION