2010-03-09 2 views
170

Я знаю, что this относится к текущему объекту. Но я не знаю, когда мне действительно нужно это использовать. Например, будет ли какая-либо разница, если я использую x вместо this.x в некоторых методах? Может быть, x будет ссылаться на переменную, которая является локальной для рассматриваемого метода? Я имею в виду переменную, которая видна только в этом методе.Когда я должен использовать «это» в классе?

Как насчет ? Могу ли я использовать его? Должен ли я использовать его. Если я просто использую method(), не будет ли он по умолчанию применяться к текущему объекту?

ответ

248

Ключевое слово this в основном используется в трех ситуациях. Первый и наиболее распространенный в методах setter для устранения неоднозначности ссылок на переменные. Во-вторых, когда необходимо передать текущий экземпляр класса в качестве аргумента методу другого объекта. Третий - это способ вызова альтернативных конструкторов из конструктора.

Дело 1: Использование this для устранения неоднозначных ссылок. В методах настройки Java мы обычно передаем аргумент с тем же именем, что и переменная частного члена, которую мы пытаемся установить. Затем мы присваиваем аргумент xthis.x. Это дает понять, что вы назначаете значение параметра «name» переменной экземпляра «name».

public class Foo 
{ 
    private String name; 

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

Случай 2: Использование this в качестве аргумента, переданного другому объекту.

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

Случай 3: Использование this для вызова альтернативных конструкторов. В комментариях trinithis правильно указал еще одно общее использование this. Когда у вас есть несколько конструкторов для одного класса, вы можете использовать this(arg0, arg1, ...) для вызова другого конструктора по вашему выбору, если вы делаете это в первой строке своего конструктора.

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

     //optional other lines 
    } 

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

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

+11

+1 Заметим, что вы также можете передать _this_ в качестве аргумента. _this_ используется не только для устранения неоднозначности объема. –

+12

Конечно, есть и 'this (arg1, arg2, ...)' внутри конструктора. –

+0

Просто интересно, если добавить другие ответы на свои собственные, это обычная практика на SO? Кажется, это происходит достаточно часто. – Hazior

4

Если у вас нет совпадающих имен переменных, это действительно просто для ясности, когда вы читаете код.

+3

Или беспорядок ..... –

+1

Когда вы постоянно видите ключевое слово '' this'', когда это необязательно, это просто шаблонный код, который делает код более трудным для чтения. – AxeEffect

+0

Я просто наткнулся на проект с открытым исходным кодом, который требует, чтобы * все * члены были префиксны с этим. Кроме того, проект очень хорошо написан, но у меня возникает соблазн попасть в религиозные дебаты с ними. – LegendLength

18

только потребность использовать this. классификатор, когда другие переменный в текущей области видимости разделяет то же имя, и вы хотите обратиться к члену экземпляра (например, Уильям описывает). Кроме того, нет разницы в поведении между x и this.x.

+3

И если у вас есть повторяющиеся имена, одна из ваших переменных должна быть переименована, поскольку ее почти однозначно называют неправильно. Или, по крайней мере, можно назвать лучше. – CaffGeek

+3

@ Chad: Это обычная практика в методах настройки Java. Однако, помимо методов setter, ваши утверждения обычно сохраняются. –

+2

Возможно, вы захотите использовать 'this.x', чтобы ваш код читался немного более четко, а также удобство обслуживания/удобочитаемость кода также является фактором, который вы должны учитывать ... –

0

Будет ли какая-либо разница, если я использую «x» вместо «this.x» в некоторых методах?

Обычно нет. Но это различие иногда:

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

Если я просто использовать «метод()», то не будет, по умолчанию, применяется к текущему объекту?

Да.Но при необходимости поясняет, что вызов выполняется этим объектом.

35

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

Конечно, еще одна причина, чтобы использовать this в том, что он вызывает IntelliSense всплывал в Иды :)

+20

+1 intellisense, yay за то, что вы ленивы :) – Tanzelax

+0

Но тогда вам нужно отменить его после того, как вы его просмотрите. Программирование утомительно! – LegendLength

0

this не влияет на результирующий код - это оператор времени компиляции и код, сгенерированный с ним или без него, будет таким же. Когда вы должны использовать его, зависит от контекста. Например, вы должны использовать его, как вы сказали, когда у вас есть локальная переменная, которая изменяет переменную класса, и вы хотите обратиться к переменной класса, а не к локальной.

Редактировать: по «результирующему коду будет то же самое» Я имею в виду, конечно, когда какая-либо переменная в локальной области не скрывает принадлежащую классу. Таким образом,

class POJO { 
    protected int i; 

    public void modify() { 
     i = 9; 
    } 

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

Итоговый код обоих методов будет таким же. Разница будет, если какой-либо метод объявляет локальную переменную с тем же именем

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

Google turned up a page on the Sun site that discusses this a bit.

Вы правы о переменной; this действительно может использоваться для дифференциации переменной метода из поля класса.

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

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

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

Те же результаты, но без возможности ошибки, когда вы случайно обратитесь к x, когда вы на самом деле имел в виду, чтобы иметь в виду x вместо этого.

Что касается использования этого метода, вы правы в отношении эффектов; вы получите те же результаты с или без него. Вы можете использовать его? Конечно. Должны ли вы использовать его? До вас, но учитывая, что я лично считаю, что бессмысленная многословность не добавляет никакой ясности (если только код не заполнен статическими операторами импорта), я не склонен использовать его сам.

+3

Это не конвенция, это механизм определения языка программы. То, что вы указали, - использование newX (я предпочитаю pX для параметра x) - это соглашение. –

+0

@Bill K: Я не понимаю различия, которые вы делаете. Я могу выбрать имя переменной ввода x, или newX, или pX, или mangroveThroatWarblerX. Как выбрать, чтобы дать ему имя, идентичное переменной, которое оно устанавливает, не является соглашением, в то время как добавляет соглашения «новый» или «p» или «Grutuitous Monty Python References»? – BlairHippo

+3

«Gratuitoud Monty Python References» - это не конвенция, это ЗАКОН. –

56

Второе важное применение this (рядом скрываясь с локальным переменным, как многие ответами уже говорят), когда доступ внешнего экземпляра из вложенного нестатического класса:

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

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

14

«этот» также полезен при вызове одного конструктора из другого:

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

Чтобы убедиться, что используются члены текущего объекта. Случаи, когда проблема безопасности потоков является проблемой, некоторые приложения могут изменять неправильные значения элементов объектов, поэтому это должно быть применено к члену, так что используется правильное значение члена объекта.

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

+0

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

+1

Да. Я знаю, что вы объясняете, это вопрос безопасности потоков. На этот вопрос нет правильного ответа, который подразумевает безопасность потоков. Если «это» необходимо для ссылки на правильный объект, то, как только он это сделает, метод или атрибут будут потокобезопасными тогда и только тогда, когда они синхронизированы. Если ссылка не является двусмысленной, она будет неоднозначной, если проблема многопоточности. –

8

this полезен в шаблоне строителя.

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

Это был тот тип ответа, который я хотел, когда я искал и оказался здесь, но у вас нет объяснения вашего кода, поэтому большинство людей, которые спрашивают об этом, не поймут, что «возвращает нового пользователя (этого); " означает, что я не ... – nckbrz

+0

Шаблон Builder используется для четкого определения параметров конструкции. Вместо того, чтобы иметь новый User (string, string) без простого способа указать, какая строка была, у вас будет новый Builder(). SetFirstName («Jane»). SetSurname («Smith»). Build(). Вы возвращаете это из функций Builder.set ...(), чтобы их можно было связать. – ChrisPhoenix

1

this - ссылка на текущий объект. Он используется в конструкторе для различения локальной и текущей переменных класса, имеющих одно и то же имя. например .:

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

this также можно использовать для вызова одного конструктора из другого конструктора. например:

public class circle { 
    int x; 

    circle() { 
     this(1); 
    } 

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

@ Ответы Виллиама Бренделя предоставили три разных варианта использования в красивом виде.

Пример использования 1:

Offical Java Страница документации на this обеспечивает те же примеры использования.

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

Он охватывает два примера:

Используя это с полем и Используя это с помощью конструктора

Использования Случай 2:

другое использование случая, который не цитируется в этом сообщении: this может использоваться для синхронизации cu rrent-объект в многопоточном приложении для защиты критического раздела данных & методов.

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

Пример использования 3:

Осуществление Builder модели зависит от использования this вернуть измененный объект.

Обратитесь к этому сообщению

Keeping builder in separate class (fluent interface)

1

Ниже приведены способы использования 'это' ключевое слово в Java:

  1. Использование this ключевое слово для обозначения переменных экземпляра текущего класса
  2. Использование this() для вызова текущего класса конструктора
  3. Использование this ключевого слова, чтобы вернуть текущий экземпляр класса
  4. Использования this ключевого слова в качестве параметра метода

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

0

Что касается William Brendel «s должности и dbconfessions вопроса о случае 2. Вот пример:

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

} 

Я видел, что это использовалось при построении отношений родитель-ребенок с объектами. Однако, пожалуйста, обратите внимание, что это упрощено ради краткости.

0

Есть много хороших ответов, но есть еще одна очень небольшая причина, чтобы повсюду поставить . Если вы попытались открыть исходные коды из обычного текстового редактора (например, блокнот и т. Д.), Использование this сделает его более понятным для чтения.

Представьте себе:

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

Это очень ясно читать с любой современной IDE, но это будет общий кошмар для чтения с обычным текстовым редактором.

Вы будете пытаться выяснить, где находится foo, пока вы не используете функцию «Найти» редактора. Тогда вы будете кричать на getStringFromSomewhere() по той же причине. И наконец, после того как вы забыли, что s, что bar = s собирается дать вам последний удар.

Сравните это так:

public void doSomething() { 
    // More codes 
    Hello.this.foo = "FOO"; 
    // More codes 
    String s = Hello.this.getStringFromSomewhere(); 
    // More codes 
    this.bar = s; 
} 
  1. Вы знаете foo переменная объявлена ​​в космическом классе Hello.
  2. Вы знаете, что getStringFromSomewhere() - это метод, объявленный и в внешнем классе.
  3. Вы знаете, что bar принадлежит к классу World, а s - это локальная переменная, объявленная в этом методе.

Конечно, всякий раз, когда вы что-то создаете, вы создаете правила. Поэтому при разработке вашего API или проекта, если ваши правила включают «если кто-то откроет все эти исходники с помощью блокнота, он или она должен застрелить себя в голове», тогда вы полностью не делаете этого.

Смежные вопросы