[java] Soll ich Instanzvariablen bei der Deklaration oder im Konstruktor instanziieren?



Answers

Eine andere Option wäre, Dependency Injection zu verwenden .

class A{
   B b;

   A(B b) {
      this.b = b;
   }
}

Dadurch entfällt die Verantwortung für das Erstellen des B Objekts aus dem Konstruktor von A Dadurch wird Ihr Code auf lange Sicht testbarer und einfacher zu warten. Die Idee ist, die Kopplung zwischen den beiden Klassen A und B zu reduzieren. Ein Vorteil, den Sie erhalten, besteht darin, dass Sie nun jedes Objekt übergeben können, das B (oder B implementiert, wenn es eine Schnittstelle ist) an den Konstruktor von A , und es wird funktionieren. Ein Nachteil ist, dass Sie die Kapselung des B Objekts aufgeben, so dass es dem Aufrufer des A Konstruktors ausgesetzt ist. Sie müssen überlegen, ob die Vorteile diesen Kompromiss wert sind, aber in vielen Fällen sind sie es.

Question

Gibt es einen Vorteil für beide Ansätze?

Beispiel 1:

class A {
    B b = new B();
}

Beispiel 2:

class A {
    B b;

    A() {
         b = new B();
    }
}



Ich wurde heute auf interessante Weise verbrannt:

class MyClass extends FooClass {
    String a = null;

    public MyClass() {
        super();     // Superclass calls init();
    }

    @Override
    protected void init() {
        super.init();
        if (something)
            a = getStringYadaYada();
    }
}

Siehst du den Fehler? Es stellt sich heraus, dass der Initialisierer a = null aufgerufen wird, nachdem der Superklassenkonstruktor aufgerufen wurde. Da der Superklassenkonstruktor init () aufruft, folgt auf die Initialisierung von a die Initialisierung von a = null .




Ich nehme an, es ist fast nur eine Frage des Geschmacks, solange die Initialisierung einfach ist und keine Logik benötigt.

Der Konstruktor-Ansatz ist etwas fragiler, wenn Sie keinen Initialisiererblock verwenden. Wenn Sie später einen zweiten Konstruktor hinzufügen und vergessen, b dort zu initialisieren, erhalten Sie nur dann null b, wenn Sie diesen letzten Konstruktor verwenden.

Weitere Informationen zur Initialisierung in Java finden Sie unter http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html (und Erläuterungen zu Initialisierungsbausteinen und anderen nicht bekannten Initialisierungsfunktionen).




Die zweite Option ist vorzuziehen, da sie die Verwendung verschiedener Logik in ctors für die Klasseninstanziierung und die Verwendung von ctors chaining ermöglicht. Z.B

class A {
    int b;

    // secondary ctor
    A(String b) {
         this(Integer.valueOf(b));
    }

    // primary ctor
    A(int b) {
         this.b = b;
    }
}

Die zweite Option ist also flexibler.




Die zweite ist ein Beispiel für eine verzögerte Initialisierung. Die erste ist eine einfachere Initialisierung, sie sind im Wesentlichen gleich.




Ich denke, Beispiel 2 ist vorzuziehen. Ich denke, die beste Vorgehensweise besteht darin, außerhalb des Konstruktors zu deklarieren und im Konstruktor zu initialisieren.




Links