2009-02-05 9 views
7

Se scrivo la seguente classe:L'uso di "questo" in Java

public class Example { 

     int j; 
     int k; 

     public Example(int j, int k) { 
      j = j; 
      k = k; 
     } 

     public static void main(String[] args) { 
      Example exm = new Example(1,2); 
      System.out.println(exm.j); 
      System.out.println(exm.k); 
     } 

} 

Il programma viene compilato, ma quando ho eseguito il programma, il metodo principale stampare due 0s. So che per dire che voglio inizializzare le variabili di istanza nel costruttore devo scrivere:

this.j = j; 
this.k = k; 

Ma se non scrivo, poi la variabile viene valutata (o considerato) in costruttore (a sinistra e sul lato mano di scrittura delle espressioni)? È l'argomento o la variabile di istanza? Fa la differenza?

Esistono altri casi in cui l'uso di this è obbligatorio?

+4

Questo tipo di errore è un buon motivo per rendere definitivi i parametri. –

+0

Puoi anche dare un'occhiata a: http://stackoverflow.com/questions/132777/do-you-prefix-your-instance-variable-with-this-in-java – VonC

+1

In uno dei posti in cui ho lavorato, loro non ha mai permesso di modificare i parametri, ma non ha mai permesso che i parametri venissero contrassegnati come "finali". E mi piace uno stile simile. È, err, elegante :) – Srikanth

risposta

6

Se non si scrive questo, si assegna l'argomento a se stesso; le variabili argomento ombreggiano le variabili di istanza.

30

Se non si scrive "this.variable" nel costruttore e se si dispone di una variabile locale (incluso il parametro function) con lo stesso nome della variabile di campo nel costruttore, la variabile locale sarà considerato; la variabile locale ombreggia il campo (aka variabile di classe).

Un posto dove "questo" è l'unico modo per andare:

class OuterClass { 
    int field; 

    class InnerClass { 
    int field; 

    void modifyOuterClassField() 
    { 
     this.field = 10; // Modifies the field variable of "InnerClass" 
     OuterClass.this.field = 20; // Modifies the field variable of "OuterClass", 
            // and this weird syntax is the only way. 
    } 
    } 
} 
+1

Bella cattura: l'orrore delle classi interne :) –

+0

@Robert: Grazie! Sì, evita il più possibile :) – Srikanth

+1

Hai sicuramente meritato un upvote, sei appena venuto in giro a cercare "questo" su google e hai trovato il tuo esempio più semplice. awesome :) – 0decimal0

5

questo è utile quando si desidera restituire l'oggetto stesso

return this; 

Questo è utile perché se una classe ha per esempio Method1() e Method2(), restituendo entrambi, è consentito scrivere chiamate come

object.Method1().Method2() 

Anche all'interno di un metodo può essere utile passare l'oggetto stesso a un'altra funzione, durante una chiamata.

3

Nel codice costruttore, si assegnano le variabili a se stessi. 'j' è la j specificata nell'argomento per il costruttore. Anche se fosse la variabile di classe j definita sopra, allora stai ancora dicendo "j = j" ... cioè non valuteremo diversamente a sinistra ea destra.

public Example(int j, int k) { 
     this.j = j; 
     this.k = k; 
    } 
10

se dici solo j nel costruttore il compilatore penserà si intende l'argomento in entrambi i casi. Così

j = j; 

assegna semplicemente il valore dell'argomento j all'argomento j (che è una dichiarazione abbastanza inutile, ma comunque valido).

Quindi, per chiarire questo problema è possibile prefisso this. per indicare che si intende la variabile membro con lo stesso nome.

L'altro utilizzo di this è quando è necessario passare un riferimento all'oggetto corrente di qualche metodo, come questa:

someObject.addEventListener(this); 

In questo esempio è necessario fare riferimento all'oggetto corrente nel suo complesso (anziché solo un membro dell'oggetto).

2

Assegnare il parametro a se stesso nell'esempio.

Più in generale: se non si antepone un ambito alla variabile, si presume l'ambito corrente, che è la funzione nel proprio caso. 'this.j' dice al jre di usare la variabile j all'interno dell'oggetto scope - la variabile membro dell'oggetto.

1

Proprio come ha detto Robert Grant, "questo" è il modo in cui si rende chiaro che si fa riferimento a una variabile membro anziché a una variabile locale.

3

Quello che stai vivendo si chiama variable shadowing. Dai un'occhiata a questa panoramica per different kinds of variables in Java.

In generale: il compilatore Java utilizza la variabile più vicina che può trovare per un compito. In un metodo, prima cercherà di trovare una variabile locale e quindi di ingrandire l'obiettivo della sua ricerca in variabili di classe e istanza.

Un'abitudine che personalmente trovo buona (altri non mi piace) è il prefisso di una variabile membro con m_ e l'utilizzo di lettere maiuscole per CONSTANT_VARIABLES che non cambiano il loro valore. Il codice in cui lo shadowing variabile viene utilizzato di proposito è molto (!) Difficile da eseguire il debug e il lavoro con.

+0

Le costanti che non cambiano mai devono essere dichiarate definitive, quindi è impossibile sovrascrivere i loro valori accidentalmente. –

5

Un altro approccio utile (anche se raramente usato) è di dichiarare parametri di metodo finale:

Il seguente blocco non si compila, avvisando così l'errore subito:

public Example(final int j, final int k) { 
     j = j; 
     k = k; 
    } 
+0

Non mi piace usare final per le variabili locali a meno che non sia richiesto (ma per esempio le variabili le uso sempre quando possibile). Lo trovo troppo confuso. Invece io uso l'evidenziazione del codice IDE. Vedi il mio commento qui http://blog.objectmentor.com/articles/2008/10/28/data-rattle#comment-2155 –

1

Per rispondere alla tua follow-up question about this with method, il inner class mentioned by Srikanth is still a valid example of using this: (con il metodo di questa volta)

public class OuterClass 
{ 
    void f() {System.out.println("Outer f()");}; 
    class InnerClass { 
     void f() { 
      System.out.println("Inner f()"); 
      OuterClass.this.f(); 
     } 
    } 
} 

hai la stessa situazione con anonymous class:

Si può fare riferimento al metodo della classe esterna da:

  • MyOuterClass.this.yOuterInstanceMethod(),
  • MyOuterClass.myOuterInstanceMethod(),
  • o semplicemente myOuterInstanceMethod()se non c'è ambiguità.
0

Questo non abbastanza rispondere alla tua domanda, ma se si utilizza Eclipse si potrebbe trovare "Assegnazione non ha alcun effetto" impostazione utile. Sono sicuro che lo sarà anche in altri IDE.

0

Per evitare questo, utilizzare un IDE (come Eclipse) e genererà avvisi in questo caso.

Inoltre, rendi i tuoi campi definitivi a meno che non siano assolutamente impossibili. Ci sono una serie di motivi (a parte questo) per farlo.

Problemi correlati