Почему ключевое слово "this" используется в Constructor и Setters? - PullRequest
0 голосов
/ 08 мая 2018

Конструктор используется для инициализации значения и присвоения его переменной класса во время создания экземпляра класса, верно?

public class Joke{
   private String jokeSetup;
   private String jokePunchLine;

   public Joke(String jokeSetup , String jokePunchLine){
       this.jokeSetup=jokeSetup;
       this.jokePunchLine=jokePunchLine;
   }
}  

Примите во внимание следующее:

public Joke(String jokeSetup , String jokePunchLine) 

Создана ли другая переменная с таким же именем?

Если это так, почему они присваиваются прежним значениям jokeSetup и jokePunchLine?

PS: Этот код создан не мной. Он был показан в видео, из которого я изучаю Java.

Ответы [ 4 ]

0 голосов
/ 08 мая 2018

Параметризованный конструктор может использоваться для инициализации значения переменным во время его создания. Если параметры и имена переменных совпадают, то в этом случае для различия между ними мы используем ключевое слово this . Это ключевое слово всегда ссылается на локальную переменную метода или класса.

0 голосов
/ 08 мая 2018

Цель конструктора - инициализировать только что созданный объект, например, заполнив его поля экземпляра (также называемые переменные экземпляра ). this используется в вашем конструкторе для ссылки на экземпляр, который инициализирует конструктор.

В вашем примере конструктора у вас есть параметры и поля экземпляра . Конструктор принимает значения параметров и присваивает эти значения полям экземпляра:

public Joke(String jokeSetup , String jokePunchLine)
//          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---- Declares parameters this
//                                                      constructor accepts when
//                                                      called
{
//                 vvvvvvvvv------------ parameter
    this.jokeSetup=jokeSetup;
//  ^^^^^^^^^^^^^^---------------------- instance field

//                     vvvvvvvvvvvvv---- parameter
    this.jokePunchLine=jokePunchLine;
//  ^^^^^^^^^^^^^^^^^^------------------ instance field
}

Конструктор может вместо этого инициализировать поля экземпляра постоянными значениями или косвенным использованием значения параметра (например, поиск чего-либо) и т. Д. Это не всегда прямое однозначное присвоение, как в вашем примере.

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

public Joke(String theJokeSetup , String theJokePunchLine)
//                 ^---------------------^---------- Note the name changes
{
//                   vvvvvvvvvvvv------------ parameter
    this.jokeSetup = theJokeSetup;
//  ^^^^^^^^^^^^^^--------------------------- instance field

//                       vvvvvvvvvvvvvvvv---- parameter
    this.jokePunchLine = theJokePunchLine;
//  ^^^^^^^^^^^^^^^^^^----------------------- instance field
}

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

Когда нет конфликта, вопрос стиля зависит от того, используете ли вы this. часть или нет. (Я всегда использую this., я нахожу это более понятным.) Например, вот еще одна версия этого конструктора, которая делает то же самое, что и ваш оригинал:

public Joke(String theJokeSetup , String theJokePunchLine)
//                 ^---------------------^---------- Note the name changes
{
//              vvvvvvvvvvvv------------ parameter
    jokeSetup = theJokeSetup;
//  ^^^^^^^^^--------------------------- instance field

//                  vvvvvvvvvvvvvvvv---- parameter
    jokePunchLine = theJokePunchLine;
//  ^^^^^^^^^^^^^----------------------- instance field
}

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

0 голосов
/ 08 мая 2018

Java имеет подразумеваемый контекст для имен символов; экземпляр класса (например, this) для нестатических контекстов и класс (например, Joke) для статических.

Это позволяет вам опустить контекст, когда нет конфликта для имени символа. Например

public String getJokeSetup() {
    return jokeSetup; // no "this." required, it's implied
}

Если для имени существует конфликт, такой как случай с аргументом метода, названным так же, как поле, вам необходимо явно определить контекст, например,

public void setJokeSetup(final String jokeSetup) {
    // you must prefix the field with "this." to differentiate it from the argument
    this.jokeSetup = jokeSetup; 
}

Наконец, вот пример, который позволяет избежать конфликта имен символов

public void setJokeSetup(final String js) {
    jokeSetup = js;
}

Довольно типично называть аргументы такими же, как поля, которым они соответствуют, но вы, безусловно, не ограничены таким соглашением.

0 голосов
/ 08 мая 2018

В классе есть поле с именем jokeSetup. У метода есть параметр с тем же именем, что и shadows в этом поле.

Итак, по сути, есть две переменные с одинаковым именем.

Использование this позволяет снова дифференцировать два различных использования одного и того же имени, так как this. Что бы всегда обозначало соответствующее поле.

И ты прибил это: слежка на самом деле не очень хорошая идея. Но этот «шаблон» на самом деле очень распространен в Java. Этого можно избежать, дав параметру другое имя, например _jokeSetup, но отклонение от общепринятых практик также является плохой практикой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...