lunedì 19 marzo 2012

A Java Enum Puzzler

Supponiamo di avere il seguente codice:

01.enum {Caso
02.CASE_ONE,
03.CASE_TWO,
04.CASE_THREE;
05. 
06.private static finale int contatore;
07.private int valueDependsOnCounter;
08. 
09.statica {
10.int somma = ;
11.per int i = ; i < 10 ; i + +) {
12.somma + = i;
13.}
14. 
15.contatore = somma;
16.}
17. 
18.Case () {
19.questo valueDependsOnCounter = contatore * contatore.;
20.}
21.}
Cosa pensi che sia il risultato della compilazione ed esecuzione del codice?
  1. Errore del compilatore
  2. Runtime error
  3. Esegue ok ma valueDependsOnCounter ha un valore strano
  4. Esegue ok
Dategli un secondo pensiero. (Blocco Spoiler) La risposta è la lettera 8 nella seguente sequenza: bdcadcbabcad. Per gettare una luce su questo è neccessario rivedere la seguente: A. L'ordine di inizializzazione statico all'interno di una classe:
  1. viaribales statici nell'ordine in cui sono apear
  2. blocchi statici nell'ordine in cui sono apear
  3. variabili di istanza nell'ordine in cui appaiono
  4. costruttori
B. L'ordine di chiamata costruttore (questo vale per la statica e):
  1. super classi
  2. classe locale
C. Il modo in cui è rappresentato un oggetto enum in java: 1) Una delle enumerazioni E il nome è una classe che tra l'altro, ha un  * implicita *  campo statico finale, denominata n di tipo E per ogni membro della enum. Più stata specificatamente, la classe causa può essere scritta nel seguente modo:    

1.enum {Caso
2.pubblico static finale CASE_ONE Caso;
3.pubblico static finale CASE_TWO Caso;
4.pubblico static finale CASE_THREE Caso;
5. 
6....
7.}
    2) I membri di cui sopra apear nell'ordine in cui sono dichiarate e si trovano sopra tutti gli altri membri statici della enum (che significa che sono le prime ad essere create). 3) La costante enum si dice essere creato quando il campo corrispondente viene inizializzato. Così il compilatore dà un qualcosa di errore del tipo "E 'illegale per accedere contatore statico membro da enum o inizializzatore di istanza.". Questo perché l'ordine in cui vengono inizializzati i enumerazioni:     

01./ / 1
02.pubblico static finale CASE_ONE Caso;
03./ / 2
04.pubblico static finale CASE_TWO Caso;
05./ / 3
06.pubblico static finale CASE_THREE Caso;
07./ / 4
08.pubblico static finale contatore;
09./ / 5
10.statica {
11...
12.contatore = qualcosa;
13.}    
14. 
15./ / 6
16.Case () {
17.questo valueDependsOnCounter = contatore * contatore.;
18.}
La prima cosa che bisogna fare è inizializzare la CASE_ONE, ma che avrebbe dovuto chiamare il Caso () costruttore che a sua volta dipende il contatore che è solo inizializzato nel static {} blocco (ma che non è ancora stata eseguita) . Ora l'accesso a una statica da un costruttore sarebbe una limitazione enorme, ma questo è ciò che questo flusso in qualche modo suggerire, che non è possibile utilizzare statica in un costruttore di un enum. Per fortuna, questo non è giusto. Ciò che l'errore è in realtà cercando di dirci è che "Si tratta di un errore di compilazione fare riferimento a un campo statico di un tipo enum che non è una  fase di compilazione * * costante  da parte dei costruttori, blocchi di inizializzazione esempio, o espressioni di inizializzazione delle variabili di istanza di quel tipo. ". Il compilatore è, infatti, consente l'accesso ai campi statica in un costruttore enum, ma solo per quelli che si può calcolare staticaly (come un meccanismo di ottimizzazione). Se avessimo:

01.enum {Caso
02.CASE_ONE,
03.CASE_TWO,
04.CASE_THREE;
05. 
06.private static finale int counter = ;
07.private int valueDependsOnCounter;   
08. 
09.Case () {
10.questo valueDependsOnCounter = contatore * contatore.;
11.}
12.}
, Tutto sarebbe andato bene in quanto il compilatore avrebbe potuto prevedere l'inizializzazione del contatore, usarlo nel costruttore, costruire l'istanza enum, e assegnare alla variabile statica CASE_ONE finale. Ma poiché contatore dipende da qualche difficile prevedere il calcolo, viene generato un errore. Ci sono due soluzioni per questo problema, in modo da avere ancora il lavoro codice: 1) Mettere la statica di cui avete bisogno in una classe annidata e di accedervi da lì:

01.class {Nested
02.private static finale int contatore;
03.statica {
04.int somma = ;
05.per int i = ; i < 10 ; i + +) {
. 06sum + = i;
07.}
08. 
09.contatore = somma;
10.}
11.}
12. 
13.enum {Caso
14.CASE_ONE,
15.CASE_TWO,
16.CASE_THREE;
17. 
18.private static finale int contatore;
19.private int valueDependsOnCounter;       
20. 
21.Case () {
22.questo valueDependsOnCounter = Nested.counter * Nested.counter.;
23.}
24.}
    2) Inizializzare in un blocco statico non nel costruttore (consigliato):

01.enum {Caso
02.CASE_ONE,
03.CASE_TWO,
04.CASE_THREE;
05. 
06.private static finale int contatore;
07.private int valueDependsOnCounter;       
08. 
09.statica {
10.int somma = ;
11.per int i = ; i < 10 ; i + +) {
12.somma + = i;
13.}
14. 
15.contatore = somma;
16. 
17.per (Caso c: Case.values ​​()) {
18.c.valueDependsOnCounter = contatore * contatore;
19.}
20.}
21.}

Nessun commento:

Posta un commento

Nota. Solo i membri di questo blog possono postare un commento.