Soll ich Instanzvariablen bei der Deklaration oder im Konstruktor instanziieren?
Gibt es einen Vorteil für einen der beiden Ansätze?
Beispiel 1:
class A {
B b = new B();
}
Beispiel 2:
class A {
B b;
A() {
b = new B();
}
}
InformationsquelleAutor der Frage DonX | 2010-01-03
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es zusätzlich die Initialisierung block, die auch im Konstruktor(en) durch den compiler:
Überprüfen Sonne Erklärung und Beratung
Vom dieses tutorial:
Darüber hinaus möchten Sie vielleicht faul initialisieren Ihrem Gebiet. In Fällen, bei der Initialisierung eines Feldes ist eine teure operation ist, Sie kann initialisiert werden, sobald es benötigt wird:
Und letztlich (wie bereits von Bill), für den Willen des management von Abhängigkeiten, ist es besser zu vermeiden Verwendung der
new
Betreiber überall innerhalb Ihrer Klasse. Statt, mit Dependency Injection vorzuziehen ist, d.h., weil jemand anderes (eine andere Klasse/framework) instanziieren und injizieren der Abhängigkeiten in Ihrer Klasse.InformationsquelleAutor der Antwort Bozho
Andere Möglichkeit wäre die Verwendung von Dependency Injection.
Dadurch entfällt die Verantwortung der Erstellung der
B
Objekt aus dem Konstruktor vonA
. Dadurch wird Ihr code besser getestet werden, und leichter zu pflegen im langen Lauf. Die Idee ist die Verringerung der Kopplung zwischen den beiden KlassenA
undB
. Ein Vorteil, den diese bietet, ist, dass jetzt können Sie beliebiges Objekt übergeben, das reichtB
(oder implementiertB
wenn es eine Schnittstelle) zuA
's Konstruktor und es wird funktionieren. Ein Nachteil ist, dass Sie aufgeben Kapselung derB
Objekt, so dass es ausgesetzt ist, an den Aufrufer derA
Konstruktor. Sie haben zu prüfen, ob die Vorteile es Wert sind, diesem trade-off, aber in vielen Fällen sind Sie.InformationsquelleAutor der Antwort Bill the Lizard
Hab ich gebrannt auf eine interessante Weise heute:
Finden Sie den Fehler? Es stellt sich heraus, dass die
a = null
Initialisierer wird aufgerufen nach den superclass-Konstruktor aufgerufen wird. Da die superclass-Konstruktor ruft init () die Initialisierung dera
ist gefolgt durch diea = null
Initialisierung.InformationsquelleAutor der Antwort Edward Falk
meine persönliche "Regel" (kaum gebrochenen):
ein block
nicht
erklärt
Konstruktor, wenn Sie benötigt Daten aus
der Konstruktor zu tun
Initialisierung
Also ich würde code wie:
Diese Weise bin ich immer 100% sicher, wo ich die Variablen Deklarationen (am Anfang eines Blocks), sowie deren Zuweisungen (sobald es Sinn macht nach der Erklärung). Dieser windet sich möglicherweise als effizienter, da Sie nie eine variable zu initialisieren mit einem Wert, der nicht verwendet wird (zum Beispiel erklären und die init-vars und dann eine exception zu werfen, bevor die Hälfte derer vars benötigt, um einen Wert haben). Sie auch nicht wind zu tun, sinnlos Initialisierung (wie int i = 0; und dann später, bevor "ich" verwendet wird, ist do i = 5;.
Ich Wert Konsistenz sehr viel, so dass nach dieser "Regel" ist etwas, was ich die ganze Zeit mache, und es macht es viel einfacher zu arbeiten mit dem code, da Sie nicht auf die Jagd um Dinge zu finden.
Kann Ihre Laufleistung variieren.
InformationsquelleAutor der Antwort TofuBeer
Beispiel 2 ist weniger flexibel. Wenn Sie hinzufügen einen anderen Konstruktor, müssen Sie daran denken, zu instanziieren, die das Feld in diesem Konstruktor als gut. Nur instanziieren Sie das Feld direkt, oder einführen, lazy loading, irgendwo in einem getter.
Wenn Instanziierung erfordert mehr als nur eine einfache
new
ist, verwenden Sie einen block-Initialisierer. Dies wird ausgeführt unabhängig der Konstruktor verwendet. E. g.InformationsquelleAutor der Antwort BalusC
Ich nehme es fast nur eine Frage des Geschmacks, solange die Initialisierung ist einfach und braucht keine Logik.
Konstruktor Ansatz ist ein bisschen mehr zerbrechlich, wenn Sie nicht verwenden einen block-Initialisierer, denn wenn Sie später hinzufügen eines zweiten Konstruktors und vergessen zu initialisieren b gibt, erhalten Sie einen null-b nur, wenn Sie diesen letzten Konstruktor.
Sehen http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html für mehr details über die Initialisierung in Java (und für Erklärungen auf initalizer Blöcke und andere nicht bekannte Initialisierungs-Funktionen).
InformationsquelleAutor der Antwort Vinko Vrsalovic
Entweder dependency injection oder lazy-Initialisierung ist immer vorzuziehen, wie bereits erläutert, durchaus auf andere Antworten.
Wenn Sie nicht wollen oder können nicht verwenden Sie diese Muster, und für die primitiven Datentypen gibt es drei zwingende Gründe die ich mir denken kann, warum es vorzuziehen, zur Initialisierung der Attribute der Klasse und außerhalb des Konstruktors:
InformationsquelleAutor der Antwort Marco Lackovic
Beide Methoden sind akzeptabel. Beachten Sie, dass im letzteren Fall
b=new B()
erhalten möglicherweise nicht initialisiert, wenn ein anderer Konstruktor vorhanden ist. Denke, dass der Initialisierer code, der außerhalb der Konstruktor wie eine gemeinsame Konstruktor und den code ausgeführt.InformationsquelleAutor der Antwort Chandra Patni
Ich denke, dass Beispiel 2 vorzuziehen ist. Ich denke, dass die beste Vorgehensweise ist außerhalb des Konstruktors deklarieren und initialisieren Sie im Konstruktor.
InformationsquelleAutor der Antwort jkeesh
Das zweite ist ein Beispiel für die verzögerte Initialisierung. Erste einfache Initialisierung, sind Sie im wesentlichen gleich.
InformationsquelleAutor der Antwort fastcodejava
Es ist ein subtiler Grund initialisiert werden außerhalb des Konstruktors, dass niemand erwähnt hat, bevor (sehr spezifisch muss ich sagen). Wenn Sie mithilfe von UML-Werkzeuge zur Generierung der Klassendiagramme aus code (reverse-engineering), die meisten der tools, die ich glauben, beachten Sie die Initialisierung von Beispiel 1 und übertragen Sie es auf ein Diagramm (wenn Sie es vorziehen, zeigen die Startwerte an, wie ich es Tue). Werden Sie nicht nehmen, diese ersten Werte aus Beispiel 2. Das ist wieder ein ganz bestimmten Grund - wenn Sie die Arbeit mit UML-tools, aber einmal habe ich gelernt, dass ich versuche, alle meine Standard-Werte, die außerhalb der Konstruktor, es sei denn, wie schon erwähnt wurde, es ist ein Problem der möglichen Ausnahme werfen oder komplizierte Logik.
InformationsquelleAutor der Antwort tulu
Ist die zweite option vorzuziehen, da es erlaubt, unterschiedliche Logik in ctors für Klassen Instanziierung und Verwendung ctors Verkettung. E. g.
Also die zweite Optionen flexibler ist.
InformationsquelleAutor der Antwort Andriy Kryvtsun