2010-05-18 7 views
38

Ho un membro static finale:In Java, un campo finale può essere inizializzato da un helper costruttore?

private final HashMap<String,String> myMap; 

desidero inizializzare utilizzando un metodo chiamato dal costruttore. Poiché myMap è definitivo, il mio metodo "helper" non è in grado di inizializzarlo direttamente. Certamente ho opzioni:

Potrei implementare il codice di inizializzazione myMap direttamente nel costruttore.

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

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

    // other initialization stuff unrelated to myMap 
} 

ho potuto avere il mio metodo di supporto costruire l'HashMap, restituirlo al costruttore, e hanno il costruttore quindi assegnare l'oggetto da myMap.

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; 
} 

Metodo # 2 va bene, però, mi chiedo se c'è qualche modo ho potuto consentire al metodo di supporto per manipolare direttamente myMap. Forse un modificatore che lo indica può essere chiamato solo dal costruttore?

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

Sai cosa faranno le persone che rispondono alla tua domanda? Sì, lo provano aprendo Eclipse e copiando il codice! :) – Simon

+5

@Simon La mia domanda richiede un'alternativa a quello che ho provato. Mi chiedo se qualcuno con una migliore conoscenza di quella lingua possa guidarmi verso una parola chiave o un paradigma di cui non sono a conoscenza. – csj

+3

la risposta è No. Fonte: specifica linguaggio Java 8.3.1.2 – mihi

risposta

12

Il metodo n. 2 è la soluzione migliore. Il problema è che se si ha un'assegnazione in un metodo privato non c'è nulla che impedisca l'altro codice nella classe all'esterno del costruttore che lo chiama, il che quindi creerebbe un problema con un tentativo di secondo assegnamento al campo finale.

Java non ha costrutto di un metodo separato che può essere chiamato solo durante la costruzione.

Per completezza, possiamo fare una terza opzione, dove si assegna la mappa in fase di inizializzazione e quindi avere il metodo di supporto riempirlo:

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

E poi:

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... 
    } 

E se si voglio davvero essere confuso puoi usare un inizializzatore invece di un costruttore, ma non dovresti farlo, quindi a meno che tu non abbia davvero bisogno di sapere, non lo espanderò.

+5

In realtà, Java ha. Si chiama costruttore ;-) – Joey

+1

@Johannes no, significa che non esiste alcuna designazione del sub-costruttore che consentirebbe l'assegnazione di variabili finali a condizione che il metodo possa essere chiamato solo dal costruttore. – corsiKa

+0

@Yishai. Grazie per l'alternativa. Inoltre, per quanto riguarda gli inizializzatori, non penso che funzionerebbe comunque, dal momento che i contenuti di HashMap dipendono effettivamente dall'argomento dato al costruttore. – csj

1

L'opzione n. 2 è l'opzione più resuable, perché è possibile condividerla tra tutti i costruttori. Quello di cui avremmo bisogno qui, sono inizializzatori di raccolta di C#. :)

(BTW: # 3 non verrà compilato)

+0

Grazie per il tuo aiuto Simon. Sapevo fin dall'inizio che il # 3 non sarebbe stato compilato. Speravo che potesse esserci un modo per renderlo legale garantendo che l'aiutante sarebbe stato chiamato a chiamare dal costruttore. Sembra che questo non sia possibile. – csj

13

Come circa l'attuazione di un costruttore privato che inizializza il vostro HashMap, e quindi avere il costruttore principale (s) chiamare tale costruttore privato?

Per 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. 
} 

È possibile modificare la firma del costruttore di supporto privato, se necessario (ad esempio, per fornire i dati dei parametri o per effettuare la firma distinta da qualsiasi costruttori pubblici).

+0

Penso che questa soluzione sia ciò che @Joey ha alluso a sopra quando ha detto: "In realtà, Java ha chiamato un costruttore", in risposta all'osservazione di Yishai che "Java non ha costrutto di un metodo separato che può essere chiamato solo durante costruzione." – cjerdonek

+0

Mi piace questa idea. Sfortunatamente, mi impedisce di dare al metodo un nome sensato (come InitializeMyMap) che rappresenta ciò che sta inizializzando. Grazie per aver postato una vecchia domanda. Apprezzo sempre nuove idee o chiarimenti su quelle vecchie. – csj

+0

Grazie, @csj. Stavo cercando una risposta alla stessa domanda e ho pensato a questo. Nessuno degli approcci precedentemente proposti funzionerebbe molto bene per il mio caso di utilizzo di inizializzare simultaneamente diversi campi finali. Per quanto riguarda il nome, sì, potrebbe essere migliore. Ma almeno è coerente con i costruttori che inizializzano qualcosa. :) Sono nuovo di Java e non sarei sorpreso se c'è una soluzione ancora migliore là fuori. – cjerdonek

Problemi correlati