Quando devo usar "this" em uma classe?

268

Eu sei que thisse refere a um objeto atual. Mas não sei quando realmente preciso usá-lo. Por exemplo, haverá alguma diferença se eu usar em xvez de this.xem alguns dos métodos? Pode ser que xse refere a uma variável que é local para o método considerado? Quero dizer variável que é vista apenas neste método.

Que tal this.method()? Posso usá-lo? Devo usá-lo. Se eu apenas usar method(), não será, por padrão, aplicado ao objeto atual?

romano
fonte

Respostas:

348

A thispalavra-chave é usada principalmente em três situações. O primeiro e mais comum é nos métodos setter para desambiguar referências de variáveis. A segunda é quando há a necessidade de passar a instância atual da classe como argumento para um método de outro objeto. A terceira é uma maneira de chamar construtores alternativos de dentro de um construtor.

Caso 1: Usando thispara desambiguar referências de variáveis. Nos métodos Java setter, geralmente passamos um argumento com o mesmo nome da variável de membro privado que estamos tentando definir. Em seguida, atribuímos o argumento xa this.x. Isso deixa claro que você está atribuindo o valor do parâmetro "name" à variável de instância "name".

public class Foo
{
    private String name;

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

Caso 2: usando thiscomo argumento passado para outro 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: Usando thispara chamar construtores alternativos. Nos comentários, trinithis apontou corretamente outro uso comum de this. Quando você tem vários construtores para uma única classe, pode this(arg0, arg1, ...)chamar outro construtor de sua escolha, desde que faça isso na primeira linha do construtor.

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

        //optional other lines
    }

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

Eu também vi thisusado para enfatizar o fato de que uma variável de instância está sendo referenciada (sem a necessidade de desambiguação), mas esse é um caso raro na minha opinião.

William Brendel
fonte
21
+1 Por mencionar que você também pode passar isso como argumento. isso não é usado apenas para desambiguação de escopo.
Alex Jasmin
12
Claro que também existe this(arg1, arg2, ...)dentro de um construtor.
Thomas Eding
12
@ Hazior: eu tendem a escrever uma resposta curta e depois a adicionar ao longo do tempo. Às vezes isso se sobrepõe às respostas de outras pessoas, às vezes não. No caso da minha edição mais recente, trinithis apontou outro uso comum thisque eu esqueci, então adicionei à minha resposta. Não vejo nada de errado nisso, porque o resultado final é uma resposta melhor em geral, que é precisamente o objetivo do SO. Também tento dar crédito sempre que possível, como fiz no caso de trinithis.
William Brendel
4
Você tem exemplos para os casos 1 e 3. Você pode dar um exemplo do caso 2 em que a instância atual da classe é usada como argumento para um método de outra classe?
Dbconfession 11/09/14
4
@ AStar Na maioria das bases de código Java com as quais trabalhei ao longo dos anos, thissó é usada se a desambiguação for realmente necessária, como no meu exemplo de setter acima. Os estilos de codificação e as "práticas recomendadas" podem variar bastante, dependendo de quem você pergunta, é claro, mas, em geral, recomendo escolher padrões razoáveis ​​e segui-los. A consistência, mesmo que apenas internamente em uma única base de código, ajuda bastante na legibilidade e manutenção.
William Brendel
71

O segundo uso importante de this(além de ocultar com uma variável local, como muitas respostas já dizem) é ao acessar uma instância externa de uma classe não estática aninhada:

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;
    }
  }
}
Christopher Oezbek
fonte
46

Você só precisa usar this- e a maioria das pessoas usa - quando há uma variável local sobreposta com o mesmo nome. (Métodos setter, por exemplo.)

Obviamente, outro bom motivo para usar thisé que ele faz com que o intellisense apareça nos IDEs :)

froadie
fonte
1
Mas então você deve retroceder depois de pesquisar. A programação é cansativa!
LegendLength
25

A única necessidade de usar o this.qualificador é quando outra variável no escopo atual compartilha o mesmo nome e você deseja consultar o membro da instância (como William descreve). Além disso, não há diferença de comportamento entre xe this.x.

Adam Robinson
fonte
3
E se você tiver nomes duplicados, uma de suas variáveis ​​deve ser renomeada, pois é quase definitivamente nomeada incorretamente. Ou, no mínimo, poderia ser nomeado melhor.
CaffGeek 9/03/10
3
@ Chade: É prática comum nos métodos setter Java. No entanto, fora dos métodos setter, suas declarações geralmente são válidas.
William Brendel
2
Você pode querer usar this.xpara tornar seu código ler um pouco mais claramente, também, a manutenção / legibilidade do código também é um fator que você deve considerar ...
Bryan Rehbein
1
@ Chad: não posso concordar com entusiasmo suficiente. Bom Deus, apenas porque "isso". permite que você dê duas variáveis ​​diferentes com o mesmo nome, por que você quer?
BlairHippo
2
@Blair: A leitura da sua resposta deixa claro que você não prefere essa prática nos métodos de criação, mas muitas pessoas preferem (eu me incluiria nessa lista). Se eu tenho um método setter que aceita um valor, claramente o valor passado deve ser o valor "novo", portanto, adicionar "novo" ao nome da variável parece adicionar redundância desnecessária à API pública.
Adam Robinson
15

"this" também é útil ao chamar um construtor de outro:

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

this é útil no padrão do construtor.

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();
    }

}
Kieren Dixon
fonte
1
Esse era o tipo de resposta que eu queria quando pesquisei e acabei aqui, mas você não tem explicação do seu código; portanto, a maioria das pessoas que pergunta sobre "isso" não entende o que "retorna um novo usuário (este);" meios, como eu não ...
nckbrz
O padrão Builder é usado para especificar parâmetros claramente na construção. Em vez de ter um novo usuário (string, string) sem uma maneira fácil de saber qual string era qual, você teria o novo Builder (). SetFirstName ("Jane"). SetSurname ("Smith"). Build (). Você retorna isso das funções Builder.set ... () para poder encadeá-las.
ChrisPhoenix
10

Há muitas boas respostas, mas há outra razão muito menor para colocar em thistodo lugar. Se você tentou abrir seus códigos-fonte a partir de um editor de texto normal (por exemplo, bloco de notas, etc.), o uso thisserá muito mais claro de se ler.

Imagina isto:

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;
        }
    }
}

Isso é muito claro para ler com qualquer IDE moderno, mas será um pesadelo total ler com um editor de texto comum.

Você lutará para descobrir onde fooreside, até usar a função "localizar" do editor. Então você gritará pelo getStringFromSomewhere()mesmo motivo. Por fim, depois de esquecer o que sé, isso bar = slhe dará o golpe final.

Compare com isso:

public void doSomething() {
    // More codes
    Hello.this.foo = "FOO";
    // More codes
    String s = Hello.this.getStringFromSomewhere();
    // More codes
    this.bar = s;
}
  1. Você sabe que fooé uma variável declarada na classe externa Hello.
  2. Você sabe que getStringFromSomewhere()é um método declarado na classe externa também.
  3. Você sabe que barpertence à Worldclasse e sé uma variável local declarada nesse método.

Obviamente, sempre que você cria algo, você cria regras. Portanto, ao projetar sua API ou projeto, se suas regras incluírem "se alguém abrir todos esses códigos-fonte com um bloco de notas, ele ou ela deve dar um tiro na cabeça", você estará totalmente bem em não fazer isso .

Jai
fonte
grande resposta @Jai
gaurav
A primeira razão para atirar seria escrever classes com várias linhas de 10k de código especialmente se o código já está parceladas para diferentes classes que não precisam ser encaixados :)
Lucio
@LuCio Lol true xD
Jai
7

A menos que você tenha nomes de variáveis ​​sobrepostos, é realmente apenas uma questão de clareza ao ler o código.

FrangoLeiteBomb
fonte
1
Quando você vê constantemente a thispalavra-chave quando não é necessária, é apenas um código padrão, tornando o código mais difícil de ler.
AxeEffect
Acabei de encontrar um projeto de código aberto que exige que todos os membros sejam prefixados com 'this'. Além disso, o projeto está muito bem escrito, mas estou tentado a entrar em debate religioso com eles.
LegendLength
4
@AxeEffect Eu sei que isso é realmente antigo, mas ... thisNÃO torna o código mais difícil de ler lmao.
Xatenev
4

A resposta de @William Brendel forneceu três casos de uso diferentes de maneira agradável.

Caso de uso 1:

Página de documentação java oficial sobre este fornece mesmos casos de uso.

Dentro de um método de instância ou construtor, essa é uma referência ao objeto atual - o objeto cujo método ou construtor está sendo chamado. Você pode se referir a qualquer membro do objeto atual de dentro de um método de instância ou de um construtor usando isso.

Abrange dois exemplos:

Usando isso com um campo e Usando isso com um construtor

Caso de uso 2:

Outro caso de uso que não foi citado nesta postagem: thispode ser usado para sincronizar o objeto atual em um aplicativo multithread para proteger a seção crítica de dados e métodos.

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

Caso de uso 3:

A implementação do padrão Builder depende do uso de thispara retornar o objeto modificado.

Consulte este post

Mantendo o Construtor em Classe Separada (Interface Fluente)

Ravindra babu
fonte
2

O Google apareceu uma página no site da Sun que discute isso um pouco.

Você está certo sobre a variável; thispode realmente ser usado para diferenciar uma variável de método de um campo de classe.

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

No entanto, eu realmente odeio essa convenção. Dar duas variáveis ​​diferentes nomes literalmente idênticos é uma receita para bugs. Eu prefiro algo como:

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

Mesmos resultados, mas sem chance de um bug ao qual você se refere acidentalmente xquando realmente pretendia se referir x.

Quanto a usá-lo com um método, você está certo sobre os efeitos; você obterá os mesmos resultados com ou sem. Você pode usá-lo? Certo. Você deveria usá-lo? Depende de você, mas considerando que pessoalmente acho que é uma verbosidade sem sentido que não adiciona nenhuma clareza (a menos que o código esteja repleto de instruções de importação estáticas), não estou inclinado a usá-lo.

BlairHippo
fonte
4
Não é uma convenção, é um mecanismo de escopo da linguagem de programa. O que você listou - usar newX (eu prefiro pX para o parâmetro x) é uma convenção.
Bill K
@ Bill K: Eu não entendo a distinção que você está fazendo. Posso optar por nomear a variável de entrada x, ou newX, ou pX ou mangroveThroatWarblerX. Como a escolha de atribuir um nome idêntico à variável que está definindo NÃO é uma convenção, ao mesmo tempo que precede convenções ARE "new" ou "p" ou "References Gratuitas de Monty Python"?
precisa saber é o seguinte
3
"Gratuitoud Monty Python References" não é uma convenção, é a LEI.
Adam Robinson
+1: Usamos um padrão de nomenclatura diferente para argumentos e variáveis ​​de método do que para variáveis ​​de classe por esse motivo. Abreviamos argumentos / métodos vars e usamos palavras completas para variáveis ​​de classe / instância.
Lawrence Dol
1
Resolvê-lo usando uma convenção de nomenclatura é, hmm, uma convenção. Resolvê-lo usando um recurso de idioma - acho que optar por nunca usar esse recurso de idioma ou sempre usá-lo seria uma convenção ... Usar isso. para cada vez que você acessar um membro, seria uma convenção. Acho que não importa muito, eu odeio isso também.
Bill K
2

A seguir estão as maneiras de usar a palavra-chave 'this' em java:

  1. Usando thispalavra-chave para referenciar variáveis ​​de instância de classe atual
  2. Usando this()para invocar o construtor de classe atual
  3. Usando thispalavra-chave para retornar a instância de classe atual
  4. Usando thispalavra-chave como parâmetro de método

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

roottraveller
fonte
1

quando existem duas variáveis, uma variável de instância e outra variável local com o mesmo nome, usamos isso. para referir o objeto em execução atual para evitar o conflito entre os nomes.

giri
fonte
1

thisé uma referência ao objeto atual. É usado no construtor para distinguir entre a variável de classe local e a atual que tem o mesmo nome. por exemplo:

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

thistambém pode ser usado para chamar um construtor de outro construtor. por exemplo:

public class circle {
    int x;

    circle() { 
        this(1);
    }

    circle(int x) {
        this.x = x; 
    }
}
nouman shah
fonte
0

Haverá alguma diferença se eu usar "x" em vez de "this.x" em alguns dos métodos?

Geralmente não. Mas às vezes faz diferença:

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

Se eu apenas usar "method ()", não será, por padrão, aplicado ao objeto atual?

Sim. Mas, se necessário, this.method()esclarece que a chamada é feita por esse objeto.

amit
fonte
0

thisnão afeta o código resultante - é o operador de tempo de compilação e o código gerado com ou sem será o mesmo. Quando você precisa usá-lo, depende do contexto. Por exemplo, você deve usá-lo, como disse, quando tiver uma variável local que oculta a variável de classe e desejar consultar a variável de classe e não a local.

edit: por "o código resultante será o mesmo", claro, quando alguma variável no escopo local não oculta a que pertence à classe. portanto

class POJO {
   protected int i;

   public void modify() {
      i = 9;
   }

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

o código resultante de ambos os métodos será o mesmo. A diferença será se algum método declarar variável local com o mesmo nome

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

Com relação à pergunta dos posts e dbconfessions de William Brendel , referente ao caso 2 . Aqui está um exemplo:

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");
    }
  }

}

Eu já vi isso usado, ao criar relações pai-filho com objetos. No entanto, observe que é simplificado por uma questão de brevidade.

Alija
fonte
0

A palavra-chave “This” em java é usada para referenciar objetos de classe atuais.

Existem 6 usos da palavra-chave "this" em java

  1. Acessando variável de nível de classe : usado principalmente se a variável local e de nível de classe for a mesma
  2. Acessando métodos de classe : esse é o comportamento padrão e pode ser ignorado
  3. Para chamar outro construtor da mesma classe
  4. Usando a palavra-chave 'this' como valor de retorno : para retornar a instância atual do método
  5. Passando a palavra-chave 'this' como argumento para o método Passing: para passar a instância da classe atual como argumento
  6. esta palavra-chave como argumento para o construtor : para passar a instância atual da classe como argumento

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

Rupesh Agrawal
fonte
-8

Para garantir que os membros do objeto atual sejam usados. Nos casos em que a segurança do encadeamento é uma preocupação, alguns aplicativos podem alterar os valores do membro de objetos incorretos; por esse motivo, isso deve ser aplicado ao membro para que o valor correto do membro do objeto seja usado.

Se o seu objeto não estiver preocupado com a segurança do encadeamento, não há motivo para especificar qual valor do membro do objeto será usado.

Outubro misterioso
fonte
Este realmente não é o caso. Não sei ao certo em que caso você está pensando, mas um exemplo pode ser útil para entender o que você está tentando dizer.
David Berger
1
Sim. Eu sei o que você está explicando envolve segurança de threads. Não há resposta correta para essa pergunta que envolva segurança de thread. Se "this" for necessário para se referir ao objeto correto, uma vez que o faça, o método ou atributo estará seguro para threads se e somente se estiver sincronizado. Se a referência for ambígua, será ambígua se um problema de multiencadeamento ou não.
David Berger