2009-02-05 4 views
7

Si escribo la clase siguiente:El uso de "este" en 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); 
     } 

} 

El programa compila, pero cuando ejecuto el programa, el método principal imprimirá dos 0s. Sé que con el fin de decir que yo quiero para inicializar las variables de instancia en el constructor que tiene que escribir:

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

Pero si no lo escribo, a continuación, se evalúa qué variable (o consideraba) en el constructor (a la izquierda y en la parte de escritura de las expresiones)? ¿Es el argumento o la variable de instancia? ¿Hace alguna diferencia?

¿Hay otros casos donde el uso de this es obligatorio?

+4

Este tipo de error es una buena razón para finalizar los parámetros. –

+0

También puede echar un vistazo a: http://stackoverflow.com/questions/132777/do-you-prefix-your-instance-variable-with-this-in-java – VonC

+1

En uno de los puestos que trabajé, nunca permitió que se cambiaran los parámetros, pero tampoco permitió que los parámetros se marcaran "final" también. Y me gusta ese estilo. Es, err, elegante :) – Srikanth

Respuesta

6

Si no escribe esto, entonces asigne el argumento a sí mismo; las variables de argumento sombrean las variables de instancia.

30

Si no escribe "this.variable" en su constructor, y si tiene una variable local (incluido el parámetro de función) con el mismo nombre que su variable de campo en el constructor, entonces la variable local será considerado; la variable local sombrea el campo (también conocida como variable de clase).

Un lugar donde "este" es el único camino a seguir:

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

Buena captura: el horror de las clases internas :) –

+0

@Robert: ¡Gracias! Sí, evita tanto como sea posible :) – Srikanth

+1

Definitivamente mereces un voto positivo, acabo de venir a buscar "esto" en google y encontré tu ejemplo más simple. increíble :) – 0decimal0

5

esto es útil cuando se desea devolver el objeto en sí

return this; 

Esto es útil porque si una clase tiene por ejemplo Method1() y Method2(), ambos devolviendo esto, se le permite escribir llamadas como

object.Method1().Method2() 

También dentro de un método puede ser útil pasar el objeto a otra función, durante una llamada.

3

En su código de constructor, está asignando variables a sí mismos. 'j' es la j especificada en el argumento para el constructor. Incluso si fuera la variable de clase j definida anteriormente, entonces todavía está diciendo "j = j" ... es decir, j no va a evaluar de manera diferente a la izquierda y a la derecha.

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

Si dicen simplemente j en su constructor entonces el compilador pensará que quiere decir el argumento en ambos casos. Así

j = j; 

simplemente asigna el valor del argumento j al argumento j (que es una declaración bastante inútil, pero no obstante válida).

Para desambiguar esto, puede hacer un prefijo this. para dejar en claro que quiere decir la variable miembro con el mismo nombre.

El otro uso de this es cuando se necesita para pasar una referencia al objeto actual a algún método, tal como este:

someObject.addEventListener(this); 

En este ejemplo necesita hacer referencia al objeto actual como un todo (en lugar de solo un miembro del objeto).

2

Usted asigna el parámetro a sí mismo en su ejemplo.

En términos más generales: si no antepone un alcance a su variable, se asume el alcance actual, que es la función en su caso. 'this.j' le dice a la jre que use la variable j dentro del alcance del objeto - la variable miembro del objeto.

1

Al igual que Robert Grant dijo, 'esto' es cómo deja en claro que se está refiriendo a una variable miembro en lugar de una variable local.

3

Lo que está experimentando se llama variable shadowing. Echa un vistazo a esta descripción general para different kinds of variables in Java.

En general, el compilador de Java usa la variable más cercana que puede encontrar para una tarea. En un método, primero tratará de encontrar una variable local y luego ampliará el foco de su búsqueda a las variables de clase e instancia.

Un hábito que personalmente me parece bueno (a otros no me gusta) es anteponer una variable miembro con m_ y usar mayúsculas para CONSTANT_VARIABLES que no cambian su valor. El código donde el sombreado variable se usa a propósito es muy (!) Difícil de depurar y trabajar.

+0

Las constantes que nunca cambian deben declararse finales, por lo que es imposible sobrescribir sus valores accidentalmente. –

5

Otro enfoque útil (aunque rara vez se utiliza) es declarar los parámetros del método definitivo:

El siguiente bloque no se compilará, avisándole de este modo al error de inmediato:

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

No me gusta utilizar las variables locales para el final a menos que sea necesario (pero por ejemplo las variables las uso siempre que sea posible). Lo encuentro demasiado desordenado. En su lugar, uso el código resaltado de mi IDE. Ver mi comentario aquí http://blog.objectmentor.com/articles/2008/10/28/data-rattle#comment-2155 –

1

para responder a sus follow-up question about this with method, la inner class mentioned by Srikanth is still a valid example of using this: (con el método de este tiempo)

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

Usted tiene la misma situación con anonymous class:

Se puede hacer referencia a los métodos de la clase externa por:

  • MyOuterClass.this.yOuterInstanceMethod(),
  • MyOuterClass.myOuterInstanceMethod(),
  • o simplemente myOuterInstanceMethod()si no hay ambigüedad.
0

Esto no acaba de responder a su pregunta, pero si se utiliza Eclipse puede encontrarse con "Asignación no tiene ningún efecto" opción útil. Estoy seguro de que esto también estará en otros IDEs.

0

Para evitar esto, use un IDE (como Eclipse) y generará advertencias en este caso.

Además, haga que sus campos sean definitivos a menos que no puedan serlo. Hay una serie de razones (aparte de esta) para hacer eso.

Cuestiones relacionadas