Standardkonstruktor vs. Inline-Feldinitialisierung
Was ist der Unterschied zwischen einem Standard-Konstruktor und nur die Initialisierung eines Objekts Felder direkt?
Welche Gründe gibt es zu bevorzugen, die eines der folgenden Beispiele, über die anderen?
Beispiel 1
public class Foo
{
private int x = 5;
private String[] y = new String[10];
}
Beispiel 2
public class Foo
{
private int x;
private String[] y;
public Foo()
{
x = 5;
y = new String[10];
}
}
InformationsquelleAutor der Frage Barry Brown | 2011-02-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Initialisers ausgeführt, bevor der Konstruktor Körper. (Das hat Konsequenzen, wenn Sie sowohl initialisers und Konstruktoren der Konstruktor-code ausführt, zweiten und überschreibt einen initialisierten Wert)
Initialisers gut, wenn du immer den gleichen Anfangswert (wie in deinem Beispiel ein array der angegebenen Größe, oder integer-spezifischer Wert), aber es kann die Arbeit zu Ihren Gunsten oder gegen Sie:
Wenn Sie viele Konstruktoren, Initialisierung von Variablen anders (D. H. mit unterschiedlichen Werten), dann initialisers sind nutzlos, da die änderungen außer Kraft gesetzt werden, und verschwenderisch.
Auf der anderen Seite, wenn Sie viele Konstruktoren, Initialisierung mit dem gleichen Wert, dann können Sie speichern Sie code-Zeilen (und machen Sie Ihren code leicht wartbarer) durch halten der Initialisierung an einem Ort.
Wie Michael schon sagte, es ist eine Frage des Geschmacks beteiligt, wie gut Sie könnten, wie Sie zu halten Sie code in einem Ort. Obwohl, wenn Sie haben viele Hersteller Ihr den code nicht an einer Stelle, in jedem Fall, so würde ich zugunsten initialisers.
InformationsquelleAutor der Antwort davin
Den Grund zu bevorzugen Beispiel ist, dass es die gleiche Funktionalität für weniger code (das ist immer gut).
Davon abgesehen, kein Unterschied.
Jedoch, wenn Sie die explizite Konstruktoren, ich würde es vorziehen, um alle Initialisierungs-code in diese (und die Kette), anstatt der Aufteilung zwischen Konstruktoren und Feld-Initialisierungen.
InformationsquelleAutor der Antwort Michael Borgwardt
Ich lieber Feld-Initialisierungen und resort zu einem Standard-Konstruktor, wenn es Komplex ist Initialisierungs-Logik zum durchführen (z.B. Auffüllen einer Karte, einem ivar hängt von dem anderen durch eine Reihe von heuristischen Schritte ausführen, etc).
@Michael B gesagt:
MichaelB (ich verbeuge mich vor dem 71+ K rep) macht absolut Sinn, aber meine Tendenz ist, dass die einfache Initialisierungen in der inline-final-Initialisierungen und machen den komplexesten Teil der Initialisierungen im Konstruktor.
InformationsquelleAutor der Antwort Bert F
Nur mit dem Unterschied, dass ich mir vorstellen kann ist, dass, wenn Sie hinzufügen würden, einen anderen Konstruktor
dann im ersten Beispiel, Sie würde nicht mehr einen Standard-Konstruktor in der Erwägung, dass im 2. Beispiel, würden Sie haben immer noch die default-Konstruktor (und konnte sogar einen Anruf tätigen, um es aus dem inneren unserer neuen Konstruktor, wenn wir es wollten)
InformationsquelleAutor der Antwort WuHoUnited
Sollten wir zugunsten Feld-Initialisierung-Konstruktor oder geben Sie einen Standardwert für ein Feld?
Werde ich nicht berücksichtigen, Ausnahmen, die möglicherweise Anstieg im Bereich Instanziierung und Feld lazy/eager Instanziierung, berühren Sie andere sorgen, als die Lesbarkeit und Wartbarkeit betrifft.
Für zwei codes, die Sie durchführen, die gleichen Logik-und liefern das gleiche Ergebnis, die Art und Weise, mit der besten Lesbarkeit und Wartbarkeit sollten bevorzugt werden.
TL;DR
Faustregel :
halten eine Konsistenz in der Art und Weise der Auswahl
jeder Weg hat seine Vorteile und seine Nachteile
zögern Sie nicht zu mischen, in beide Richtungen in eine gleiche Klasse, je nach Spezifität
zögern Sie nicht und nutzen Feld-Initialisierungen für Sie nicht teure Umschreibungen Sammlung von Feldern zu verhindern, dass
NullPointerException
.in Klassen mit einem einzigen Konstruktor, der Feld-Initialisierer Weg ist oft besser lesbar und weniger ausführlich
in Klassen mit mehreren Konstruktoren, wenn Konstruktoren haben keine oder nur sehr wenige Kopplung zwischen Ihnen, die Feld-Initialisierer Weg ist oft besser lesbar und weniger ausführlich.
in Klassen mit mehreren Konstruktoren wo die Klassen deklarieren viele Felder, wie die Felder mit Standard-Werten kann gestreut werden, Sie bewerten, in einer zentralen Konstruktor sollte besser sein. Also den Konstruktor Weg, sollten bevorzugt werden.
in den anderen Fällen von Klassen mit mehreren Konstruktoren,
keine der Möglichkeiten ist wirklich besser.
Mit einem sehr einfachen code, der die Zuordnung während der Feld Erklärung scheint mir besser und es ist.
Dies ist weniger ausführlich und mehr direkt :
als den Konstruktor Weg :
In Reale Klassen mit, so dass echte Besonderheiten sind die Dinge anders.
In der Tat, nach Besonderheiten auftreten, wird eine Weg, der andere oder jemand von Ihnen sollten bevorzugt werden.
Allgemeingültigkeit
Ändern Sie nicht die Regeln für die Entscheidung zwischen Feldern der gleichen Klasse und zwischen den Klassen zu.
Besonderheiten zu Gunsten der Valorisierung Felder im Konstruktor :
Unter Verwendung von Feld-Initialisierer Wert-Feld würde fehleranfällig sein, als der Wert definiert überschrieben werden können, während der Konstruktor Ausführung.
Ermittlung der Standard-Felder Werte ist härter als Felder mit Standardwerten kann werden sichtbar entfernt.
Besonderheiten zu Gunsten der Valorisierung Felder in Ihrer Erklärung:
Den OP-Beispiel-code veranschaulicht diesen Fall.
Es ist weniger ausführlich, und da wir nur einen Konstruktor, der es nicht scatter die Instanziierung Logik.
Wenn die Instanziierung von Validierungsregeln und die übergebenen Parameter haben keine oder nur sehr wenige Kopplung zwischen Konstruktoren, wir sind in einer ähnlichen Konfiguration wie die einzelnen Konstruktor-Fall : Feld-Initialisierer Weg ist oft besser lesbar und weniger ausführlich.
Collections
Felder (Liste, Karte, etc...).Instanziieren Ihre konkreten Klassen während Ihrer Erklärung ist oft eine gewünschte Kürzel, wie es ändert sich nicht wirklich den Zustand des zugrunde liegenden Instanz, es ist vielmehr ein Weg, um zu verhindern, dass einige
NullPointException
und zu verringern, boilerplate code in der Bearbeitung von code.Spezifität mit nicht echter Vorteil für die eine oder andere Weise:
Dass in einer Klasse mehrere Konstruktoren Durchführung der gemeinsamen Bearbeitung begünstigt die Erscheinung von einem zentralen Konstruktor führt, dass die Logik und die alle anderen Konstruktoren delegieren.
Zu vermeiden, die Streuung der Initialisierung Regeln der Instanz, die zwischen mehreren Konstruktoren und Feld-Initialisierungen, scheint es relevanter zu sammeln-Felder-Belegung mit Standardwerten und Gültigkeitsregeln in dieser zentralen Konstruktor.
So, zuweisen von Standard-Werten in Feld-Initialisierungen oder in der zentralen Konstruktor aufgerufen, der von allen anderen Konstruktoren ist in Erster Linie Stellungnahme-Basis : Präferenz, um zu sehen, alle default-Werte in der Spitze der Klasse oder legen Sie Sie in den Körper des zentralen Konstruktor.
Studie Fall 1
Werde ich anfangen, von einer einfachen
Car
Klasse, ich werde zu aktualisieren, um diese zu veranschaulichen Punkte.Car
erklären 4 Felder und 3 Konstruktoren, die relation zwischen Ihnen.1.Geben Sie einen Standardwert im Feld intializers für alle Felder ist unerwünscht
Angegebenen Standardwerte in die Felder der Erklärung sind nicht alle zuverlässig.
Nur
name
undorigin
Felder haben wirklich die default-Werte.nbSeat
undcolor
Felder sind zunächst geschätzt, in Ihrer Erklärung, dann werden diese überschrieben werden können in den Konstruktoren mit Argumenten.Es ist fehleranfällig und zudem mit dieser Art der Wertschätzung Felder, die Klasse, sinkt die Zuverlässigkeit. Wie konnte
verlassen Sie sich auf jedem Standard-Wert zugewiesen werden, während die Felder der Erklärung Weile hat es sich bewährt, nicht zuverlässig für die beiden Felder ?
2.Mithilfe der Konstruktor Wert alle Felder und sich auf die Konstruktoren der Verkettung in Ordnung ist
Diese Lösung ist wirklich in Ordnung, da es nicht schaffen, Vervielfältigung, sammelt er all die Logik an einem Ort : der Konstruktor mit der maximalen Anzahl von Parametern.
Es hat einen einzigen Nachteil : die Anforderung an die Kette der Aufruf zu einem anderen Konstruktor.
Aber ist es ein Nachteil ?
3.Geben Sie einen Standardwert im Feld intializers für Felder, die Konstruktoren nicht zuordnen, um Ihnen einen neuen Wert, der ist besser, aber hat immer noch Duplizierung Probleme
Werden wir den Wert der Felder in Ihrer Deklaration mit default-Werten für jede erzeugte Instanz und verwenden Sie den Konstruktor für Felder ohne default-Wert für jede erzeugte Instanz.
Durch nicht die Bewertung
nbSeat
undcolor
Felder in der Erklärung, die wir klar unterscheiden-Felder mit default-Werten und Feldern ohne.Diese Lösung ist ziemlich gut, aber es wiederholt die Instanziierung Logik in jedem Auto-Instanz im Gegensatz zu der vorherigen Lösung.
In diesem einfachen Beispiel, könnten wir anfangen zu verstehen, der Vervielfältigung Problem aber es scheint nur ein wenig nervig.
In realen Fällen, die Duplizierung ist möglicherweise viel wichtiger als Konstruktor ausführen kann, die Berechnung und die Validierung.
Mit einem einzigen Konstruktor der Durchführung der Instanziierung Logik wird also sehr hilfreich.
Damit letztlich die Zuordnung in die Felder, die Erklärung nicht immer ersparen, den Konstruktor an einen anderen Konstruktor delegieren.
Hier ist eine verbesserte version.
4.Geben Sie einen Standardwert im Feld intializers für Felder, die Konstruktoren nicht zuordnen, um Ihnen einen neuen Wert und verlassen sich auf die Konstruktoren der Verkettung in Ordnung ist
Studie bei 2
Ändern wir den ursprünglichen
Car
Klasse.Jetzt
Car
erklären 5 Felder und 3 Konstruktoren, die keine Beziehung zwischen Ihnen.1.Mithilfe der Konstruktor Wert-Felder mit default-Werten ist unerwünscht
Da wir keinen Wert auf
name
undorigin
Felder in der Erklärung, und wir haben nicht einen gemeinsamen Konstruktor natürlich aufgerufen durch andere Konstruktoren, sind wir gezwungen, die Einführung einerinitDefaultValues()
- Methode, und rufen Sie in jedem Konstruktor.Wir haben also nicht vergessen, die diese Methode aufrufen.
2.Geben Sie einen Standardwert im Feld intializers für Felder, die Konstruktoren nicht zuordnen, um Ihnen einen neuen Wert in Ordnung ist
Hier brauchen wir nicht zu haben
initDefaultValues()
Methode und nennen es.Feld-Initialisierungen den job.
Abschluss
In allen Fällen) die Wertschätzung der Felder im Feld-Initialisierungen sollten nicht durchgeführt werden für alle Felder, aber nur für diejenigen, die nicht überschrieben werden kann durch einen Konstruktor.
Use case 1) Im Falle mehrerer Konstruktoren mit der gemeinsamen Bearbeitung zwischen Ihnen, es ist in Erster Linie Stellungnahme-basiert.
Lösung 2 (Mithilfe der Konstruktor Wert alle Felder und sich auf die Konstruktoren der Verkettung) und Lösung 4 (Geben Sie einen Standardwert im Feld intializers für Felder, die Konstruktoren nicht zuordnen, um Ihnen einen neuen Wert und verlassen sich auf die Konstruktoren der Verkettung) erscheinen als die meisten lesbare, wartbare und robuste Lösungen.
Für Klassen, deklarieren viele Felder, wie die Felder mit Standard-Werten kann gestreut werden, Sie bewerten, in einer zentralen Konstruktor sollte besser werden.
Use case 2) Bei mehreren Konstruktoren, mit dem gemeinsamen Verarbeitung/Beziehung zwischen Ihnen, wie in der einzigen Konstruktor Fall Lösung 2 (Geben Sie einen Standardwert im Feld intializers für Felder, die Konstruktoren nicht zuordnen, um Ihnen einen neuen Wert) sieht besser aus.
InformationsquelleAutor der Antwort davidxxx