2010-05-18 3 views
38

Ich habe ein letztes nicht-statisches Element:Kann in Java ein letztes Feld von einem Konstruktorhelfer initialisiert werden?

private final HashMap<String,String> myMap; 

ich es initialisieren möchte eine Methode, mit dem Konstruktor aufgerufen werden. Da myMap endgültig ist, kann meine "Helfer" -Methode es nicht direkt initialisieren. Natürlich habe ich Optionen:

Ich könnte den myMap-Initialisierungscode direkt im Konstruktor implementieren.

MyConstructor (String someThingNecessary) 
{ 
    myMap = new HashMap<String,String>(); 

    myMap.put("blah","blahblah"); 
    // etc... 

    // other initialization stuff unrelated to myMap 
} 

Ich konnte mein Helfer-Methode haben die HashMap zu bauen, schicken Sie es an den Konstruktor, und haben der Konstruktor dann das Objekt zu myMap zuweisen.

MyConstructor (String someThingNecessary) 
{ 
    myMap = InitializeMyMap(someThingNecessary); 

    // other initialization stuff unrelated to myMap 
} 

private HashMap<String,String> InitializeMyMap(String someThingNecessary) 
{ 
    HashMap<String,String> initializedMap = new HashMap<String,String>(); 

    initializedMap.put("blah","blahblah"); 
    // etc... 

    return initializedMap; 
} 

Methode # 2 ist in Ordnung, aber ich frage mich, ob es irgendeine Art und Weise, das ich der Hilfsmethode direkt werden könnte myMap manipulieren. Vielleicht kann ein Modifikator, der darauf hinweist, nur vom Konstruktor aufgerufen werden?

MyConstructor (String someThingNecessary) 
{ 
    InitializeMyMap(someThingNecessary); 

    // other initialization stuff unrelated to myMap 
} 


// helper doesn't work since it can't modify a final member 
private void InitializeMyMap(String someThingNecessary) 
{ 
    myMap = new HashMap<String,String>(); 

    myMap.put("blah","blahblah"); 
    // etc... 
} 
+0

Wissen Sie, was die Leute tun, die Ihre Frage beantworten? Ja, sie werden es ausprobieren, indem Sie Eclipse öffnen und Ihren Code kopieren! :) – Simon

+5

@Simon Meine Frage fordert eine Alternative zu dem, was ich versucht habe. Ich frage mich, ob jemand mit besseren Kenntnissen dieser Sprache mich zu einem Schlüsselwort oder Paradigma führen kann, das mir unbekannt ist. – csj

+3

die Antwort ist Nr. Quelle: Java Sprachspezifikation 8.3.1.2 – mihi

Antwort

12

Methode # 2 ist Ihre beste Option. Das Problem ist, dass, wenn Sie eine Zuweisung in einer privaten Methode haben, nichts anderen Code in der Klasse außerhalb des Konstruktors verhindert, der sie aufruft, was dann ein Problem mit einer versuchten zweiten Zuweisung zum letzten Feld erzeugen würde.

Java hat kein Konstrukt einer separaten Methode, die nur während der Konstruktion aufgerufen werden kann.

Für Vollständigkeit können wir eine dritte Möglichkeit Gebrauch machen, wo Sie die Karte bei der Initialisierung zuweisen und dann die Hilfsmethode füllen haben:

private final HashMap<String, String> myMap = new HashMap<String, String(); 

Und dann:

MyConstructor (String someThingNecessary) 
{ 
    initializeMyMap(someThingNecessary); 

    // other initialization stuff unrelated to myMap 
} 


// helper doesn't work since it can't modify a final member 
private void initializeMyMap(String someThingNecessary) 
{ 

    myMap.clear(); 
    myMap.put("blah","blahblah"); 
    // etc... 
    } 

Und wenn Sie wirklich verwirrend sein möchten, können Sie einen Initialisierer anstelle eines Konstruktors verwenden, aber Sie sollten das nicht tun, also, wenn Sie wirklich nicht wissen müssen, werde ich darauf nicht erweitern.

+5

Eigentlich hat Java. Er heißt Konstruktor ;-) – Joey

+1

@Johannes nein, er meint, dass es keine Unterkonstruktor-Bezeichnung gibt, die die Zuweisung finaler Variablen unter der Bedingung erlauben würde, dass die Methode nur vom Konstruktor aus aufgerufen werden kann. – corsiKa

+0

@ Yishai. Danke für die Alternative. Auch in Bezug auf Initialisierer denke ich nicht, dass es trotzdem funktionieren würde, da der HashMap-Inhalt tatsächlich von dem Argument abhängt, das dem Konstruktor gegeben wird. – csj

1

Option # 2 ist die am meisten wiederverwendbare Option, da Sie sie unter allen Konstruktoren freigeben können. Was wir hier brauchen, sind Sammlungsinitialisierer von C#. :)

(BTW: # 3 wird nicht kompilieren)

+0

Danke für deine Hilfe Simon. Ich wusste von Anfang an, dass # 3 nicht kompilieren würde. Ich hatte gehofft, dass es einen Weg geben könnte, es legal zu machen, indem ich garantiere, dass der Helfer nur vom Konstrukteur aufrufbar ist. Es scheint, dass dies nicht möglich ist. – csj

13

Wie über einen privaten Konstruktor implementieren, die Ihr HashMap initialisiert, und dann Haupt Konstruktor (n), dass private Konstruktor aufrufen?

Für example--

// Helper function to initialize final HashMap. 
private MyConstructor() 
{ 
    myMap = new HashMap<String,String>(); 
    myMap.put("blah","blah"); 
} 

MyConstructor (String someThingNecessary) 
{ 
    // Initialize the HashMap. 
    this(); 
    // Other initialization code can follow. 
} 

Sie können die Unterschrift des privaten Helfer Konstruktor nach Bedarf ändern (zum Beispiel Parameterdaten zur Verfügung zu stellen oder die Signatur unterscheidet sich von öffentlichen Konstrukteuren zu machen).

+0

Ich denke, diese Lösung ist, worauf @Joey oben anspielte, als er sagte: "Eigentlich hat Java. Es heißt ein Konstruktor," als Reaktion auf Yishais Bemerkung, dass "Java kein Konstrukt einer separaten Methode hat, die nur während aufgerufen werden kann Konstruktion." – cjerdonek

+0

Ich mag diese Idee. Leider hindert es mich daran, der Methode einen vernünftigen Namen (wie InitializeMyMap) zu geben, der das repräsentiert, was sie initialisiert. Danke, dass du eine alte Frage gestellt hast. Ich schätze immer neue Ideen oder die Klärung von alten. – csj

+0

Danke, @csj. Ich suchte nach einer Antwort auf dieselbe Frage und dachte darüber nach. Keiner der zuvor vorgeschlagenen Ansätze würde für meinen Anwendungsfall der gleichzeitigen Initialisierung mehrerer Endfelder sehr gut funktionieren. Was den Namen angeht, ja, könnte es besser sein. Aber zumindest stimmt es damit überein, dass Konstruktoren etwas initialisieren. :) Ich bin neu in Java und wäre nicht überrascht, wenn es eine noch bessere Lösung gibt. – cjerdonek

Verwandte Themen