Perché inizializzatori di istanza java?

Qual è il senso di “Instance Initializers” in Java?
Non possiamo semplicemente mettere quel blocco di codice all’inizio del costruttore?

Li uso molto spesso, in genere per creare e compilare Map in un’unica istruzione (anziché utilizzare un brutto blocco statico):

private static final Map CODES = new HashMap() { { put("A", "Alpha"); put("B", "Bravo"); } }; 

Un interessante e utile abbellimento a questo è la creazione di una mappa non modificabile in una dichiarazione:

 private static final Map CODES = Collections.unmodifiableMap(new HashMap() { { put("A", "Alpha"); put("B", "Bravo"); } }); 

Più ordinata rispetto all’utilizzo di blocchi statici e gestione di assegnazioni singolari a finali, ecc.

E un altro consiglio: non abbiate paura di creare metodi che semplificano il vostro blocco di istanze:

 private static final Map CODES = new HashMap() { { put("Alpha"); put("Bravo"); } void put(String code) { put(code.substring(0, 1), code); } }; 

Potresti inserire il codice all’inizio di ogni costruttore. Tuttavia, questo è esattamente il punto di un inizializzatore di istanza: il suo codice è applicato a tutti i costruttori, il che può essere utile se si hanno molti costruttori e un po ‘di codice che è comune a tutti loro.

(Se hai appena iniziato con la programmazione, potresti non sapere che è ansible creare molti costruttori per la stessa class (purché assumano parametri diversi), questo è noto come overload del costruttore . costruttore, quindi un inizializzatore di istanza non è davvero molto utile (Modifica: a meno che non lo si abusi in mode creative, come illustrato nelle altre risposte)).

È ansible utilizzare l’inizializzatore di istanza quando si dichiara una class anonima, ad es. Quando si perpetra l’Idioma di inizializzazione Double Brace .

 List mylist = new ArrayList(){{add("a"); add("b"); add("c");}}; 

Qui puoi inizializzare l’object anche se non puoi aggiungere nulla al costruttore (perché la class è anonima).

Poiché tutti gli esempi di codice qui utilizzano classi anonime, ho riunito questa class (leggermente orribile) che dimostra l’utilizzo di inizializzatori di istanza in una class “corretta”. È ansible utilizzarli per eseguire elaborazioni complesse o gestire le eccezioni al momento dell’inizializzazione. Si noti che questi blocchi vengono eseguiti prima dell’esecuzione del costruttore, ma il costruttore viene eseguito prima dell’esecuzione degli inizializzatori in una class figlio:

 import java.util.Scanner; public class InstanceInitializer { int x; { try { System.out.print("Enter a number: "); x = Integer.parseInt(new Scanner(System.in).nextLine()); } catch (NumberFormatException e) { x = 0; } } String y; { System.out.print("Enter a string: "); y = new Scanner(System.in).nextLine(); for(int i = 0; i < 3; i++) y += y; } public InstanceInitializer() { System.out.println("The value of x is "+x); System.out.println("The value of y is "+y); } public static class ChildInstanceInitializer extends InstanceInitializer { { y = "a new value set by the child AFTER construction"; } } public static void main(String[] args){ new InstanceInitializer(); new InstanceInitializer(); System.out.println(); System.out.println(new ChildInstanceInitializer().y); // This is essentially the same as: System.out.println(new InstanceInitializer(){ {y = "a new value set by the child AFTER construction";} }.y); } } 

Questo produce (qualcosa di simile):

 Enter a number: 1 Enter a string: a The value of x is 1 The value of y is aaaaaaaa Enter a number: q Enter a string: r The value of x is 0 The value of y is rrrrrrrr Enter a number: 3 Enter a string: b The value of x is 3 The value of y is bbbbbbbb a new value set by the child AFTER construction Enter a number: s Enter a string: Hello The value of x is 0 The value of y is HelloHelloHelloHelloHelloHelloHelloHello a new value set by the child AFTER construction 

Si noti che la stringa "nuovo valore" non è impostata fino a quando il costruttore della class genitore è già stato chiamato.