Das mag wirklich einfach klingen. Aber ich bin neu in Java. Mit den paar anfänglichen Stunden des Lernens, die ich bisher gemacht habe, bin ich ständig verwirrt von der Redundanz in der Syntax einer neuen Objektdeklaration:
%Vor%Insbesondere
%Vor% Warum in der Welt möchte jemand das Schlüsselwort TypeName
(zB String
, Character
, etc ...) zweimal eingeben? Ich verstehe, dass es kurze Hände von:
Aber das sind eher Ausnahmen als Regeln. Kann mich jemand bitte aufklären? Thx.
Dies ist überhaupt nicht redundant. Es gibt zwei Schritte, um eine Variable zu verwenden:
Deklaration : Dieser Schritt teilt der VM mit, wie der statische Footprint der Variablen aussehen wird. Zum Beispiel: Object a;
wird nur die Grundfläche in der Klasse deklariert Object
sichtbar, während Integer b;
wird alle Fußabdruck in der Integer
Klasse und alle vererbten Elternklassen, bis zu Object
sichtbar erklärt hat. Dies ist für den statischen Teil.
Instanziierung : Dieser Schritt teilt der VM mit, wie der dynamische Footprint der Variablen aussehen wird. Zum Beispiel: List<String> c = new LinkedList<String>();
, dann c.put("foo");
das LinkedList
's Umsetzung der put()
Methode verwenden, wenn auch das, was sichtbar ist, ist List::put()
. Manchmal benötigen Sie diese Art der Deklaration / Instanziierung, müssen diese jedoch überschreiben, um auf eine sehr spezifische Methode zuzugreifen, die mit dem statischen Footprint nicht sichtbar ist. Zum Beispiel wollen wir ein Verfahren als public void method1(Object obj)
erklärt betrachten und Sie wissen , dass die obj
Instanz tatsächlich ein Integer
ist, damit Sie speziell die dynamische Fußabdruck verwenden indem Sie das Objekt hineinwerfen: int value = ((Integer) obj).intValue();
Nun zum String a = "A";
-Teil. Java hat die "primitiven" Klassen aus Vereinfachungsgründen in Kurzschrift geschrieben. Genauer gesagt können Sie seit Java 1.5:
Und alles funktioniert. Aber was ist der Unterschied? Betrachten Sie diesen Code:
%Vor%gibt
aus %Vor% Warum? Da die JVM versucht, Speicher so viel wie möglich wieder zu verwenden, und da a
und b
sind die Schaffung neuer Instanzen einer String
, sie teilen nicht den gleichen Speicherplatz. Allerdings c
und d
wird mit Konstante String-Werten (dies ist eine Compiler-Optimierung) und damit auf das exakt gleiche String
Objekt zeigen.
Weil Sie manchmal etwas tun wollen wie:
%Vor%oder
%Vor%oder
%Vor%Mit anderen Worten, nur weil Sie einen zu speichernden Typ deklarieren, heißt das nicht immer, dass Sie ihn mit einer neuen Instanz dieser Klasse initialisieren möchten.
Sie können eine neue Instanz einer untergeordneten Klasse verwenden, wenn Sie bei der Verwendung von Schnittstellen eine Vererbung oder eine Schnittstellenimplementierung verwenden.
Manchmal möchten Sie vielleicht auch ausdrücklich, dass etwas anfangs null ist und es später füllt.
Warum in der Welt möchte jemand Geben Sie das Schlüsselwort TypeName ein (z. B. String, Zeichen, etc ...) zweimal?
Weil du zwei Dinge tust:
Die zwei Typen sind nicht notwendigerweise die gleichen, z. B.
%Vor%Sie sind wahrscheinlich gewohnt, Sprachen wie PHP dynamisch einzugeben, wenn Variablen keinen Typ haben. Der Vorteil, den Sie mit den statischen Typdeklarationen von Java erhalten, ist, dass viele Programmierfehler vom Compiler abgefangen werden (sogar in einer modernen IDE, während Sie tippen). Zum Beispiel, wenn Sie einen einfachen Fehler machen:
%Vor% Der Compiler wird Sie sofort darauf hinweisen, dass etwas mit Ihrem Programm nicht stimmt - und das nur, weil es weiß, dass der deklarierte Typ Map
keine Methode siez()
hat.
Einige moderne statisch typisierte Sprachen wie C # und Scala verwenden Inferenz , um Ihnen das "Beste aus beiden Welten" zu geben Sie können die Typdeklaration weglassen, und der Compiler wird davon ausgehen, dass er dem Typ des Objekts entspricht, das Sie ihm zuweisen. Solche Sprachen erlauben jedoch immer explizite Typdeklarationen, da Typinferenz nicht immer möglich oder wünschenswert ist (wie im obigen Beispiel, wo die Variable die Schnittstelle und nicht die konkrete Klasse verwenden soll).
Viele gute Antworten hier, warum es notwendig ist. Du hast Recht, dass es oft überflüssig erscheint. Java wurde oft (nicht unfair) als etwas kritisiert, äh ... ausführlich. Es gibt ein paar Abkürzungen. z.B. für Strings String s="Abc"
(nicht eigentlich eine Verknüpfung, es ist ein bisschen anders, und besser, in dem Sie nicht explizit ein neues Objekt erstellen). Es wird auch eine Verringerung der Duplizierung in den Erklärungen in Java 7 für Generika geben.
Das liegt daran, dass es keine implizite Möglichkeit gibt, den Wert eines komplexen Objekts zuzuweisen.
Wenn Sie int a = 3;
oder double b = 2.5;
eingeben, können Sie den Typ auf der rechten Seite implizit angeben.
In OOP müssen Sie einen Konstruktor verwenden, deshalb müssen Sie new TypeName()
machen. Dies gibt Ihnen auch die Möglichkeit, Parameter zum Einrichten des Objekts zu übergeben.
Ein weiterer Grund ist, wenn Sie Schnittstellen verwenden. So können Sie tun:
%Vor%und sogar:
%Vor%Dies liegt daran, dass Sie bei der Arbeit mit Schnittstellen den Variablentyp in der Regel nicht als Schnittstellenimplementierung, sondern als Schnittstelle selbst definieren möchten. Sonst gäbe es keine Möglichkeit anzugeben, welche Implementierung verwendet werden soll.
Eine weitere nützliche Sache sind Generika:
%Vor%Java 7 wird das vereinfachen
%Vor%, damit Sie <SomeType>
nicht zweimal eingeben müssen (dies wird besonders in Maps schmerzhaft).
Nun, eine Variable muss einen Typ haben. Und wenn Sie eine Instanz eines Objekts erstellen, müssen Sie angeben, um welchen Typ es sich handelt. Und natürlich müssen diese nicht gleich sein. Sie können beispielsweise eine Zeichenfolge auf eine Objektvariable setzen. Natürlich könnte man etwas haben, um die Dinge etwas einfacher zu machen:
%Vor% So wurde es in C # gemacht. Aber ich nehme an, dass sie in Java kein Bedürfnis dafür gesehen haben.
Ich bin damit einverstanden, dass Java nach modernen Standards recht ausführlich ist, aber es ist auch ganz einfach zu lesen und es gibt nicht viel syntaktischen Zucker, Sie zu verwirren.
Es gibt stark typisierte Sprachen, die "Typ-Inferenz" unterstützen (wie zB Scala). Java ist einfach nicht einer von ihnen (obwohl es in Java 7 eine Art Rückschlüsse auf generische Argumente geben wird). Obwohl der Variablentyp in diesen Sprachen nicht deklariert ist, kann der Compiler eindeutig auf ihn schließen und trotzdem Typfehler erkennen. Zum Beispiel (nicht Java):
%Vor%In Java gibt es viele Fälle, in denen Sie rechts einen bestimmten konkreten Typ einem allgemeineren Typ auf der linken Seite zuweisen. Zum Beispiel:
%Vor% Dies ist ein guter Stil, da Ihr Code nicht von einer bestimmten Implementierung abhängt. Wenn Sie Implementierungen wechseln müssen (z. B. benötigen Sie schnellere Suchvorgänge von einem Hash-basierten Set
), ändert sich nur die rechte Seite des Initialisierers.
Aus diesem Grund ist es besonders wichtig, öffentliche APIs mit den richtigen Abstraktionen anstelle von konkreten Typen zu deklarieren.