2013-04-05 10 views
10

Mentre la ricerca another question, sono stato sorpreso di scoprire che il seguente codice Java viene compilato senza errori:Utilizzando this.var durante l'inizializzazione del var

public class Clazz { 
    int var = this.var + 1; 
} 

Nel mio JDK6, var ottiene inizializzato a 1.

Il codice precedente ha una semantica ben definita o il suo comportamento non è definito? Se si dice che è ben definito, si prega di citare le parti pertinenti del JLS.

+0

Cosa c'è che non va qui? –

+0

@Sudhanshu: 'var' viene utilizzato per inizializzare' var'. – NPE

+0

Innanzitutto, this.var = 0, quindi lo aggiungi per 1, quindi diventerà 1 –

risposta

4

Viene menzionato di passaggio nell'esempio 8.3.2.3-1 in section 8.3.2.3. Nel testo l'esempio

class Z { 
    static int peek() { return j; } 
    static int i = peek(); 
    static int j = 1; 
} 
class Test { 
    public static void main(String[] args) { 
     System.out.println(Z.i); 
    } 
} 

la didascalia dice:

... l'inizializzazione variabile per i utilizza il metodo della classe peek per accedere al valore della variabile j prima j è stato inizializzato dal suo inizializzatore variabile, a quel punto ha ancora il suo valore predefinito (§4.12.5).

Questo dovrebbe mappare direttamente alla situazione.

+0

Brillante, è così, grazie. – NPE

0

Introduction of Chapter 16

capitolo 16 descrive il modo preciso in cui il linguaggio garantisce che le variabili locali sono decisamente impostati prima dell'uso. Mentre tutte le altre variabili vengono inizializzate automaticamente su un valore predefinito, il linguaggio di programmazione Java non inizializza automaticamente le variabili locali per evitare errori di programmazione del mascheramento.

3

Chapter 8.3.2.2. paragraph 2:

espressioni di inizializzazione per le variabili di istanza sono autorizzati a fare riferimento all'oggetto corrente questo (§15.8.3) e di utilizzare la parola chiave super (§15.11.2, §15.12).

Anche se il paragrafo successivo aggiunge:

L'utilizzo di variabili di istanza le cui dichiarazioni comparire testualmente dopo l'uso a volte è limitato, anche se queste variabili di istanza sono di portata. Vedi §8.3.2.3 per le regole precise che governano il riferimento futuro alle variabili di istanza.

-1

Niente di sbagliato in questo. questa parola chiave fa riferimento all'oggetto corrente e viene utilizzato per differenziare la variabile locale e la variabile di istanza. Il valore della variabile locale può essere assegnato anche alla variabile di istanza, anche viceversa. Ciò significa che possiamo assegnare il valore della variabile di istanza a una variabile locale.

fare riferimento al capitolo 4.12.3 Tipi di variabili da http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf (pagina 80). L'esempio è anche dato qui.

 **Example 4.12.3-1. Different Kinds of Variables** 
     class Point { 
     static int numPoints; // numPoints is a class variable 
     int x, y; // x and y are instance variables 
     int[] w = new int[10]; // w[0] is an array component 
     int setX(int x) { // x is a method parameter 
     int oldx = this.x; // oldx is a local variable 
     this.x = x; 
     return oldx; 
     } 
    } 
+1

La domanda OP è diversa. La domanda riguarda i "riferimenti avanzati". La domanda OP non sta parlando della variabile locale e della variabile di istanza. – AmitG

0

Uso di semplice nome non consentito in caso di forward references come da JSL. Quindi è necessario utilizzare questa parola chiave per accedere a tali variabili.

class UseBeforeDeclaration { 
    int h = j++; // error - `j` read before declaration 
    int l = this.j * 3; // ok - not accessed via simple name 
    int j; 
} 
+1

Questo è stato determinato nella domanda collegata all'inizio di questa domanda. Quello che chiede NPE è: abbiamo la garanzia che 'var' sarà uno dopo' int var = this.var + 1; 'e perché? – assylias

0

Poiché tutte le variabili non locali viene assegnato un valore iniziale (e l'assegnazione avviene-prima di tutto), non v'è alcun problema per leggere in qualsiasi momento.

La specifica vieta in alcuni casi l'accesso in alcune situazioni, ragionando sul fatto che tali accessi sono molto probabilmente errori di programmazione. Ma se fosse stato loro permesso di accedere, avrebbero una semantica ben definita.

In realtà un programmatore può facilmente aggirare le restrizioni e "indirettamente" accedere al campo in ogni caso; la semantica di quell'accesso è la stessa dell'accesso "diretto" se fosse consentita.

int var = this.var + 1;  // suppose javac forbids this 

int var = this.getVar() + 1; // but can javac forbid this?