Ich habe kürzlich begonnen, Effective Java von Joshua Bloch zu lesen. Ich fand die Idee des Builder-Musters [Punkt 2 im Buch] wirklich interessant. Ich habe versucht, es in meinem Projekt zu implementieren, aber es gab Kompilierungsfehler. Folgendes habe ich im Wesentlichen versucht:
Die Klasse mit mehreren Attributen und ihre Builder-Klasse:
public class NutritionalFacts {
private int sodium;
private int fat;
private int carbo;
public class Builder {
private int sodium;
private int fat;
private int carbo;
public Builder(int s) {
this.sodium = s;
}
public Builder fat(int f) {
this.fat = f;
return this;
}
public Builder carbo(int c) {
this.carbo = c;
return this;
}
public NutritionalFacts build() {
return new NutritionalFacts(this);
}
}
private NutritionalFacts(Builder b) {
this.sodium = b.sodium;
this.fat = b.fat;
this.carbo = b.carbo;
}
}
Klasse, in der ich versuche, die obige Klasse zu verwenden:
public class Main {
public static void main(String args[]) {
NutritionalFacts n =
new NutritionalFacts.Builder(10).carbo(23).fat(1).build();
}
}
Ich erhalte den folgenden Compilerfehler:
Eine einschließende Instanz, die effektivjava.BuilderPattern.NutritionalFacts.Builder enthält, ist erforderlich. NutritionalFacts n = new NutritionalFacts.Builder (10) .carbo (23) .fat (1) .build ();
Ich verstehe nicht, was die Nachricht bedeutet. Bitte erkläre. Der obige Code ähnelt dem von Bloch in seinem Buch vorgeschlagenen Beispiel.
quelle
Antworten:
Machen Sie den Builder zu einer
static
Klasse. Dann wird es funktionieren. Wenn es nicht statisch ist, würde es eine Instanz seiner eigenen Klasse erfordern - und es geht nicht darum, eine Instanz davon zu haben und sogar das Erstellen von Instanzen ohne den Builder zu verbieten.Referenz: Verschachtelte Klassen
quelle
Builder
iststatic
in dem Beispiel im Buch (Seite 14, Zeile 10 in der 2. Ausgabe).Sie sollten die Builder-Klasse als statisch festlegen und die Felder endgültig machen und Getter haben, um diese Werte abzurufen. Geben Sie keine Setter für diese Werte an. Auf diese Weise wird Ihre Klasse vollkommen unveränderlich sein.
Und jetzt können Sie die Eigenschaften wie folgt einstellen:
quelle
final
Felder sind nur dann sinnvoll, wenn die Felder bei der Initialisierung immer benötigt werden. Wenn nicht, sollten die Felder nicht seinfinal
.Sie versuchen, statisch auf eine nicht statische Klasse zuzugreifen. Wechseln Sie
Builder
zustatic class Builder
und es sollte funktionieren.Die von Ihnen angegebene Beispielverwendung schlägt fehl, da keine Instanz
Builder
vorhanden ist. Eine statische Klasse für alle praktischen Zwecke wird immer instanziiert. Wenn Sie es nicht statisch machen, müssen Sie sagen:Weil Sie
Builder
jedes Mal ein neues bauen müssten .quelle
Überprüfen Sie dieses Plugin, um einen inneren Builder in Intellij IDEA zu generieren: https://github.com/analytically/innerbuilder
quelle
Sie müssen die
Builder
innere Klasse als deklarierenstatic
.Konsultieren Sie einige Dokumentationen sowohl für nicht statische innere Klassen als auch für statische innere Klassen .
Grundsätzlich können die nicht statischen Instanzen der inneren Klassen nicht ohne angehängte Instanz der äußeren Klasse existieren.
quelle
Sobald Sie eine Idee haben, können Sie in der Praxis Lomboks finden
@Builder
viel bequemer finden.@Builder
Mit dieser Option können Sie automatisch den Code erstellen, der erforderlich ist, damit Ihre Klasse mit Code wie dem folgenden instanziierbar ist:Offizielle Dokumentation: https://www.projectlombok.org/features/Builder
quelle
Dies bedeutet, dass Sie keinen Enclose-Typ erstellen können. Dies bedeutet, dass Sie zuerst eine Instanz der "übergeordneten" Klasse zuordnen müssen und dann aus dieser Instanz verschachtelte Klasseninstanzen erstellen können.
Verschachtelte Klassen
quelle
Die Builder-Klasse sollte statisch sein. Ich habe momentan keine Zeit, den Code darüber hinaus tatsächlich zu testen, aber wenn es nicht funktioniert, lass es mich wissen und ich werde einen weiteren Blick darauf werfen.
quelle
Ich persönlich bevorzuge den anderen Ansatz, wenn Sie 2 verschiedene Klassen haben. Sie benötigen also keine statische Klasse. Dies dient im Wesentlichen dazu, das Schreiben zu vermeiden,
Class.Builder
wenn Sie eine neue Instanz erstellen müssen.Sie können Ihren Builder also folgendermaßen verwenden:
quelle
Wie viele hier bereits angegeben haben, müssen Sie die Klasse machen
static
. Nur eine kleine Ergänzung - wenn Sie möchten, gibt es einen etwas anderen Weg ohne statische.Bedenken Sie. Implementieren eines Builders durch Deklarieren von
withProperty(value)
Typensetzern innerhalb der Klasse und Zurückgeben eines Verweises auf sich selbst. Bei diesem Ansatz haben Sie eine einzelne und eine elegante Klasse, die threadsicher und prägnant ist.Bedenken Sie:
Weitere Java Builder- Beispiele finden Sie hier.
quelle
Sie müssen die Builder- Klasse in die statische Klasse Builder ändern . Dann wird es gut funktionieren.
quelle