Использование «этого» в Java - PullRequest
7 голосов
/ 05 февраля 2009

Если я напишу следующий класс:

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

}

Программа компилируется, но когда я запускаю ее, метод main выводит два 0. Я знаю, что для того, чтобы сказать, что я хочу инициализировать переменные экземпляра в конструкторе, мне нужно написать:

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

Но если я не пишу это, то какая переменная вычисляется (или учитывается) в конструкторе (слева и со стороны записи выражений)? Это аргумент или переменная экземпляра? Это имеет значение?

Существуют ли другие случаи, когда использование this обязательно?

Ответы [ 13 ]

30 голосов
/ 05 февраля 2009

Если вы не пишете «this.variable» в своем конструкторе, и если у вас есть локальная переменная (включая параметр функции) с тем же именем, что и ваша переменная поля в конструкторе, то локальная переменная будет считаться ; локальная переменная затеняет поле (переменная класса).

Единственное место, куда "это" - единственный путь:

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.
    }
  }
}
10 голосов
/ 05 февраля 2009

Если вы скажете просто j в своем конструкторе, то компилятор будет думать, что вы имеете в виду аргумент в обоих случаях. Так

j = j;

просто присваивает значение аргумента j аргументу j (что является довольно бессмысленным, но, тем не менее, допустимым утверждением).

Таким образом, чтобы устранить неоднозначность, вы можете добавить префикс this., чтобы дать понять, что вы имеете в виду переменную-член с тем же именем.

Другое использование this - это когда вам нужно передать ссылку на текущий объект какому-либо методу, например, так:

someObject.addEventListener(this);

В этом примере вам нужно сослаться на текущий объект в целом (а не просто на элемент объекта).

6 голосов
/ 05 февраля 2009

Если вы не пишете это, тогда вы присваиваете аргумент себе; переменные аргумента скрывают переменные экземпляра.

5 голосов
/ 05 февраля 2009

Еще один полезный подход (хотя и редко используемый) заключается в объявлении параметров метода final:

Следующий блок не скомпилируется, поэтому сразу предупреждает вас об ошибке:

  public Example(final int j, final int k) {
       j = j;
       k = k;
  }
5 голосов
/ 05 февраля 2009

это полезно, когда вы хотите вернуть сам объект

return this;

Это полезно, потому что, если в классе есть, например, Method1 () и Method2 (), которые оба возвращают это, вам разрешено писать вызовы типа

object.Method1().Method2()

Также внутри метода может быть полезно передать сам объект другой функции во время вызова.

3 голосов
/ 05 февраля 2009

То, что вы испытываете, называется переменная тень . Взгляните на этот обзор для различных типов переменных в Java .

Вообще говоря: компилятор Java использует ближайшую переменную, которую он может найти для назначения. В методе он сначала попытается найти локальную переменную, а затем расширит фокус своего поиска до переменных класса и экземпляра.

Одна привычка, которую я лично нахожу полезной (другим это не нравится), - это префикс переменной-члена с помощью m_ и использование прописных букв для CONSTANT_VARIABLES, которые не меняют своего значения. Код, где намеренно используется затенение переменных, очень (!) Трудно отлаживать и работать с ним.

3 голосов
/ 05 февраля 2009

В вашем коде конструктора вы присваиваете переменные себе. «j» - это j, указанное в аргументе для конструктора. Даже если это была переменная класса j, определенная выше, вы все равно говорите «j = j» ... т.е. j не будет по-разному оцениваться слева и справа.

  public Example(int j, int k) {
       this.j = j;
       this.k = k;
  }
2 голосов
/ 05 февраля 2009

Вы присваиваете параметр себе в своем примере.

В более общем смысле: если вы не добавляете область видимости к своей переменной, предполагается текущая область видимости - которая является функцией в вашем случае. «this.j» указывает jre использовать переменную j в области видимости объекта - переменную-член объекта.

1 голос
/ 06 февраля 2009

Чтобы ответить на ваш дополнительный вопрос об этом с помощью метода , внутренний класс , упомянутый Srikanth, все еще является верным примером использования этого: (с методом на этот раз)

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

У вас такая же ситуация с анонимным классом :

Вы можете обратиться к методам внешнего класса:

  • MyOuterClass.this.yOuterInstanceMethod(),
  • MyOuterClass.myOuterInstanceMethod()
  • или просто myOuterInstanceMethod() если нет двусмысленности .
1 голос
/ 05 февраля 2009

Точно так же, как сказал Роберт Грант, «это» позволяет понять, что вы ссылаетесь на переменную-член вместо локальной.

...