¿Cuándo debo usar "esto" en una clase?


269

Sé que se thisrefiere a un objeto actual. Pero no sé cuándo realmente necesito usarlo. Por ejemplo, ¿habrá alguna diferencia si lo uso en xlugar de this.xalgunos de los métodos? ¿Puede xreferirse a una variable que sea local para el método considerado? Me refiero a la variable que solo se ve en este método.

¿Qué hay de this.method()? ¿Puedo usarlo? ¿Debo usarlo? Si solo uso method(), ¿no se aplicará, por defecto, al objeto actual?

Respuestas:


349

La thispalabra clave se usa principalmente en tres situaciones. El primero y más común está en los métodos de establecimiento para desambiguar referencias variables. El segundo es cuando hay una necesidad de pasar la instancia de clase actual como argumento a un método de otro objeto. El tercero es como una forma de llamar a constructores alternativos desde dentro de un constructor.

Caso 1: Utilizando thispara desambiguar referencias variables. En los métodos de establecimiento de Java, comúnmente pasamos un argumento con el mismo nombre que la variable de miembro privado que estamos intentando establecer. Luego asignamos el argumento xa this.x. Esto deja en claro que está asignando el valor del parámetro "nombre" a la variable de instancia "nombre".

public class Foo
{
    private String name;

    public void setName(String name) {
        this.name = name;
    }
}

Caso 2: Uso thiscomo argumento pasado a otro objeto.

public class Foo
{
    public String useBarMethod() {
        Bar theBar = new Bar();
        return theBar.barMethod(this);
    }

    public String getName() {
        return "Foo";
    }
}

public class Bar
{
    public void barMethod(Foo obj) {
        obj.getName();
    }
}

Caso 3: Utilizando thispara llamar a constructores alternativos. En los comentarios, trinithis señaló correctamente otro uso común de this. Cuando tiene múltiples constructores para una sola clase, puede usar this(arg0, arg1, ...)para llamar a otro constructor de su elección, siempre que lo haga en la primera línea de su constructor.

class Foo
{
    public Foo() {
        this("Some default value for bar");

        //optional other lines
    }

    public Foo(String bar) {
        // Do something with bar
    }
}

También he visto que thissolía enfatizar el hecho de que se hace referencia a una variable de instancia (sin la necesidad de desambiguación), pero ese es un caso raro en mi opinión.


21
+1 Por mencionar que también puedes pasar esto como argumento. esto no solo se usa para la desambiguación del alcance.
Alex Jasmin

12
Por supuesto, también hay this(arg1, arg2, ...)dentro de un constructor.
Thomas Eding

12
@Hazior: tiendo a escribir una respuesta corta y luego la agrego con el tiempo. A veces eso se superpone con las respuestas de otras personas, a veces no. En el caso de mi última edición, Trinithis señaló otro uso común thisque olvidé, así que lo agregué a mi respuesta. No veo nada malo en esto porque el resultado final es una mejor respuesta en general, que es precisamente el propósito de SO. También trato de dar crédito siempre que sea posible, como lo hice en el caso de trinithis.
William Brendel

44
Tiene ejemplos para los casos 1 y 3. ¿Puede dar un ejemplo del caso 2 donde la instancia de clase actual se usa como argumento para un método de otra clase?
dbconfession

44
@AStar En la mayoría de las bases de código Java con las que he trabajado a lo largo de los años, thissolo se usa si la desambiguación es realmente necesaria, como en mi ejemplo de configuración anterior. Los estilos de codificación y las "mejores prácticas" pueden variar ampliamente dependiendo de a quién le pregunte, por supuesto, pero en general, recomiendo elegir patrones razonables y apegarse a ellos. La coherencia, incluso internamente dentro de una única base de código, contribuye en gran medida a la legibilidad y la facilidad de mantenimiento.
William Brendel

71

El segundo uso importante de this(además de esconderse con una variable local como ya dicen muchas respuestas) es cuando se accede a una instancia externa desde una clase no estática anidada:

public class Outer {
  protected int a;

  public class Inner {
    protected int a;

    public int foo(){
      return Outer.this.a;
    }

    public Outer getOuter(){
      return Outer.this;
    }
  }
}

46

Solo necesita usar this, y la mayoría de la gente solo lo usa, cuando hay una variable local superpuesta con el mismo nombre. (Métodos Setter, por ejemplo).

Por supuesto, otra buena razón para usar thises que hace que intellisense aparezca en IDEs :)


1
Pero luego tiene que retrocederlo después de buscarlo. ¡La programación es agotadora!
LegendLength

25

La única necesidad de usar el this.calificador es cuando otra variable dentro del alcance actual comparte el mismo nombre y desea referirse al miembro de la instancia (como describe William). Aparte de eso, no hay diferencia en el comportamiento entre xy this.x.


3
Y si tiene nombres duplicados, una de sus variables debe renombrarse, ya que casi definitivamente se nombra incorrectamente. O al menos, podría ser nombrado mejor.
CaffGeek

3
@Chad: es una práctica común en los métodos de establecimiento de Java. Sin embargo, fuera de los métodos de establecimiento, sus declaraciones generalmente se mantienen.
William Brendel

2
Es posible que desee usar this.xpara que su código se lea un poco más claramente también, la facilidad de mantenimiento / legibilidad del código también es un factor que debe considerar ...
Bryan Rehbein

1
@ Chad: No puedo estar de acuerdo con suficiente entusiasmo. Dios mío, solo porque "esto". le permite dar el mismo nombre a dos variables diferentes, ¿por qué QUIERE?
BlairHippo

2
@Blair: Al leer su respuesta, queda claro que no prefiere esta práctica en los métodos de establecimiento, pero muchas personas sí (me incluiría en esa lista). Si tengo un método de establecimiento que toma un valor, claramente el valor pasado es el "nuevo", por lo que agregar "nuevo" al nombre de la variable parece agregar redundancia innecesaria a la API pública.
Adam Robinson

15

"esto" también es útil cuando se llama a un constructor desde otro:

public class MyClass {
    public MyClass(String foo) {
        this(foo, null);
    }
    public MyClass(String foo, String bar) {
        ...
    }
}

11

this es útil en el patrón de construcción.

public class User {

    private String firstName;
    private String surname;

    public User(Builder builder){
        firstName = builder.firstName;
        surname = builder.surname;
    }

    public String getFirstName(){
        return firstName;
    }

    public String getSurname(){
        return surname;
    }

    public static class Builder {
        private String firstName;
        private String surname;

        public Builder setFirstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public Builder setSurname(String surname) {
            this.surname = surname;
            return this;
        }

        public User build(){
            return new User(this);
        }

    }

    public static void main(String[] args) {
        User.Builder builder = new User.Builder();
        User user = builder.setFirstName("John").setSurname("Doe").build();
    }

}

1
Este fue el tipo de respuesta que quería cuando busqué y terminé aquí, pero no tiene una explicación de su código, por lo que la mayoría de las personas que preguntan sobre "esto", no entenderán qué "devolver un nuevo usuario (esto)"; significa, como yo no ...
nckbrz

El patrón Builder se usa para especificar parámetros claramente en la construcción. En lugar de tener un nuevo Usuario (cadena, cadena) sin una forma fácil de saber qué cadena era cuál, tendría un nuevo Generador (). SetFirstName ("Jane"). SetSurname ("Smith"). Build (). Devuelve esto desde las funciones Builder.set ... () para poder encadenarlas.
ChrisPhoenix

10

Hay muchas buenas respuestas, pero hay otra razón muy pequeña para poner en thistodas partes. Si ha intentado abrir sus códigos fuente desde un editor de texto normal (por ejemplo, un bloc de notas, etc.), el uso thishará que sea mucho más claro de leer.

Imagina esto:

public class Hello {
    private String foo;

    // Some 10k lines of codes

    private String getStringFromSomewhere() {
        // ....
    }

    // More codes

    public class World {
        private String bar;

        // Another 10k lines of codes

        public void doSomething() {
            // More codes
            foo = "FOO";
            // More codes
            String s = getStringFromSomewhere();
            // More codes
            bar = s;
        }
    }
}

Esto es muy claro para leer con cualquier IDE moderno, pero será una pesadilla total para leer con un editor de texto normal.

Te costará descubrir dónde fooreside, hasta que uses la función "buscar" del editor. Entonces gritarás getStringFromSomewhere()por la misma razón. Por último, después de que hayas olvidado lo que ses, eso bar = ste dará el golpe final.

Compáralo con esto:

public void doSomething() {
    // More codes
    Hello.this.foo = "FOO";
    // More codes
    String s = Hello.this.getStringFromSomewhere();
    // More codes
    this.bar = s;
}
  1. Sabes que fooes una variable declarada en clase externa Hello.
  2. Sabes que también getStringFromSomewhere()es un método declarado en la clase externa.
  3. Sabes que barpertenece a la Worldclase, y ses una variable local declarada en ese método.

Por supuesto, cada vez que diseñas algo, creas reglas. Así, mientras que el diseño de su API o proyecto, si sus reglas incluyen "si alguien abre todos estos códigos fuente con un bloc de notas, él o ella le debe disparar / a sí misma en la cabeza", entonces usted está totalmente bien no hacer esto .


gran respuesta @Jai
Gaurav

La primera razón para disparar sería escribir clases con varias líneas de código de 10k, especialmente si el código ya está dividido en diferentes clases que no necesitan estar anidadas :)
LuCio

@LuCio Lol verdadero xD
Jai

7

A menos que tenga nombres de variables superpuestos, es solo por claridad cuando está leyendo el código.


1
Cuando ve constantemente la thispalabra clave cuando no es necesaria, es solo un código repetitivo que hace que el código sea más difícil de leer.
AxeEffect

Acabo de encontrar un proyecto de código abierto que exige que todos los miembros tengan el prefijo 'this'. Aparte de eso, el proyecto está muy bien escrito, pero estoy tentado a entrar en un debate religioso con ellos.
LegendLength

44
@AxeEffect Sé que esto es muy antiguo pero ... thisNO hace que el código sea más difícil de leer lmao.
Xatenev

4

La respuesta de @William Brendel proporcionó tres casos de uso diferentes de una manera agradable.

Caso de uso 1:

La página de documentación oficial de Java sobre esto proporciona los mismos casos de uso.

Dentro de un método de instancia o un constructor, esta es una referencia al objeto actual, el objeto cuyo método o constructor se está llamando. Puede hacer referencia a cualquier miembro del objeto actual desde un método de instancia o un constructor mediante este.

Cubre dos ejemplos:

Usar esto con un campo y usar esto con un constructor

Caso de uso 2:

Otro caso de uso que no se ha citado en esta publicación: thisse puede utilizar para sincronizar el objeto actual en una aplicación multiproceso para proteger la sección crítica de datos y métodos.

synchronized(this){
    // Do some thing. 
}

Caso de uso 3:

La implementación del patrón Builder depende del uso de thispara devolver el objeto modificado.

Consulte esta publicación

Mantener el generador en una clase separada (interfaz fluida)


2

Google abrió una página en el sitio de Sun que habla un poco sobre esto.

Tienes razón sobre la variable; thisde hecho puede usarse para diferenciar una variable de método de un campo de clase.

    private int x;
    public void setX(int x) {
        this.x=x;
    }

Sin embargo, realmente odio esa convención. Dar dos variables diferentes, literalmente, nombres idénticos es una receta para los errores. Prefiero algo como:

    private int x;
    public void setX(int newX) {
        x=newX;
    }

Los mismos resultados, pero sin posibilidad de un error al que accidentalmente te refieres xcuando realmente querías referirte a él x.

En cuanto a usarlo con un método, tienes razón sobre los efectos; obtendrá los mismos resultados con o sin él. ¿Puedes usarlo? Por supuesto. ¿Deberías usarlo? Depende de usted, pero dado que personalmente creo que es una verbosidad inútil que no agrega ninguna claridad (a menos que el código esté lleno de declaraciones de importación estáticas), no estoy dispuesto a usarlo yo mismo.


44
No es una convención, es un mecanismo de alcance del lenguaje del programa. Lo que enumeró: usar newX (prefiero pX para el parámetro x) es una convención.
Bill K

@ Bill K: No entiendo la distinción que estás haciendo. Puedo elegir nombrar la variable de entrada x, o newX, o pX, o mangroveThroatWarblerX. ¿Cómo elegir darle un nombre idéntico a la variable que está configurando NO es una convención, mientras que anteponer "nuevo" o "p" o "Referencias de Monty Python Gratuitas" SON convenciones?
BlairHippo

3
"Referencias de Gratuitoud Monty Python" no es una convención, es la LEY.
Adam Robinson

+1: Usamos un estándar de nomenclatura diferente para argumentos y variables de método que el de las variables de clase por este motivo. Abreviamos argumentos / métodos vars y usamos palabras completas para las variables de clase / instancia.
Lawrence Dol

1
Resolverlo usando una convención de nomenclatura es, hmm, una convención. Resolverlo usando una función de idioma: supongo que elegir nunca usar esa función de idioma o usarla siempre sería una convención ... Usar esto. por cada vez que accedes a un miembro sería una convención. Supongo que no importa mucho, odio esto también.
Bill K

2

Las siguientes son las formas de usar la palabra clave 'this' en java:

  1. Utilizando this palabras clave para referirse a las variables de instancia de clase actuales
  2. Utilizando this() para invocar el constructor de clase actual
  3. Usar thispalabras clave para devolver la instancia de clase actual
  4. Usar thispalabra clave como parámetro de método

https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html


1

cuando hay dos variables, una variable de instancia y otra variable local del mismo nombre, entonces usamos esto. para hacer referencia al objeto de ejecución actual para evitar el conflicto entre los nombres.


1

thises una referencia al objeto actual. Se utiliza en el constructor para distinguir entre la variable de clase local y la actual que tienen el mismo nombre. p.ej:

public class circle {
    int x;
    circle(int x){
        this.x =x;
        //class variable =local variable 
    }
} 

thistambién se puede usar para llamar a un constructor desde otro constructor. p.ej:

public class circle {
    int x;

    circle() { 
        this(1);
    }

    circle(int x) {
        this.x = x; 
    }
}

0

¿Habrá alguna diferencia si uso "x" en lugar de "this.x" en algunos de los métodos?

Usualmente no. Pero a veces hace la diferencia:

  class A {
     private int i;
     public A(int i) {
        this.i = i; // this.i can be used to disambiguate the i being referred to
     }
  }

Si solo uso "method ()", ¿no se aplicará, por defecto, al objeto actual?

Si. Pero si es necesario, this.method()aclara que la llamada la realiza este objeto.


0

thisno afecta el código resultante: es un operador de tiempo de compilación y el código generado con o sin él será el mismo. Cuando tienes que usarlo, depende del contexto. Por ejemplo, debe usarlo, como dijo, cuando tiene una variable local que sombrea la variable de clase y desea referirse a la variable de clase y no a la local.

editar: por "el código resultante será el mismo" quiero decir, por supuesto, cuando alguna variable en el ámbito local no oculta la que pertenece a la clase. Así

class POJO {
   protected int i;

   public void modify() {
      i = 9;
   }

   public void thisModify() {
      this.i = 9;
   }
}

El código resultante de ambos métodos será el mismo. La diferencia será si algún método declara una variable local con el mismo nombre

  public void m() {
      int i;
      i = 9;  // i refers to variable in method's scope
      this.i = 9; // i refers to class variable
  }

0

Con respecto a las publicaciones de William Brendel y la pregunta de dbconfessions , con respecto al caso 2 . Aquí hay un ejemplo:

public class Window {

  private Window parent;

  public Window (Window parent) {
    this.parent = parent;
  }

  public void addSubWindow() {
    Window child = new Window(this);
    list.add(child);
  }

  public void printInfo() {
    if (parent == null) {
      System.out.println("root");
    } else {
      System.out.println("child");
    }
  }

}

He visto esto usado, al construir relaciones padre-hijo con objetos. Sin embargo, tenga en cuenta que se simplifica por razones de brevedad.


0

La palabra clave "this" en java se usa para referir objetos de clase actuales.

Hay 6 usos de la palabra clave "this" en java

  1. Acceso a la variable de nivel de clase : se usa principalmente si la variable de nivel de clase y local es la misma
  2. Acceso a métodos de clase : este es el comportamiento predeterminado y puede ignorarse
  3. Para llamar a otro constructor de la misma clase
  4. Usar la palabra clave 'this' como valor de retorno : para devolver la instancia actual del método
  5. Pasar 'esta' palabra clave como argumento al método Pasar: para pasar la instancia de clase actual como argumento
  6. esta palabra clave como argumento para el constructor : para pasar la instancia de clase actual como argumento

ref: https://stacktraceguru.com/java/this-keyword-in-java


-8

Para asegurarse de que se utilizan los miembros del objeto actual. En los casos en que la seguridad de subprocesos es una preocupación, algunas aplicaciones pueden cambiar los valores de miembros de objetos incorrectos, por esa razón esto debería aplicarse al miembro para que se use el valor de miembro de objeto correcto.

Si su objeto no está preocupado por la seguridad del subproceso, entonces no hay razón para especificar qué valor del miembro del objeto se utiliza.


Este realmente no es el caso. Ni siquiera estoy seguro de en qué caso está pensando, pero un ejemplo podría ser útil para comprender lo que está tratando de decir.
David Berger

1
Si. Sé que lo que estás explicando implica la seguridad del hilo. No hay una respuesta correcta a esta pregunta que implique la seguridad del hilo. Si "esto" es necesario para referirse al objeto correcto, una vez que lo haga, el método o atributo será seguro para subprocesos si y solo si está sincronizado. Si la referencia es ambigua, será ambigua si el multihilo es un problema o no.
David Berger
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.