수업에서 "this"를 언제 사용해야합니까?


267

나는 그것이 this현재 객체 를 참조 한다는 것을 알고 있습니다. 하지만 언제 사용해야하는지 모르겠습니다. 예를 들어, 일부 방법 x대신에 사용하면 차이가 this.x있습니까? 수 있음 x고려 방법에 대한 로컬 변수를 참조 할 것인가? 나는이 방법에서만 볼 수있는 변수를 의미합니다.

무엇에 대해 this.method()? 사용할 수 있습니까? 사용해야합니까? 방금을 사용 method()하면 기본적으로 현재 객체에 적용되지 않습니까?

답변:


347

this키워드는 주로 세 가지 상황에서 사용됩니다. 첫 번째이자 가장 일반적인 것은 setter 메소드에서 변수 참조를 명확하게하는 것입니다. 두 번째는 현재 클래스 인스턴스를 다른 객체의 메서드에 대한 인수로 전달해야 할 때입니다. 세 번째는 생성자 내에서 대체 생성자를 호출하는 방법입니다.

사례 1 :this 변수 참조를 명확하게하기 위해 사용 . Java setter 메소드에서는 일반적으로 설정하려는 개인 멤버 변수와 동일한 이름의 인수를 전달합니다. 그런 다음 인수 x를에 할당합니다 this.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인스턴스 변수가 참조되고 있다는 사실을 강조하는 데 사용되었지만 (명확한 필요성이 있음) 내 의견으로는 드문 경우입니다.


21
+1 당신은 또한 이것을 인수로 전달할 수 있다고 언급했습니다 . 이것은 범위 명확화에만 사용되는 것은 아닙니다.
Alex Jasmin 18

12
물론 this(arg1, arg2, ...)생성자 내부 에도 있습니다.
Thomas Eding

12
@ Hazior : 나는 짧은 대답을 쓰고 시간이 지남에 따라 그것을 추가하는 경향이 있습니다. 때로는 다른 사람들의 대답과 겹치지 만 때로는 그렇지 않습니다. 내 최신 편집의 경우, trinithis는 this내가 잊어 버린 다른 일반적인 용도를 지적 하여 내 답변에 추가했습니다. 최종 결과가 전체적으로 더 나은 답변이기 때문에 이것에 아무런 문제가 없습니다. 정확히 SO의 목적입니다. 또한 trinithis의 경우와 마찬가지로 가능한 한 신용을 제공하려고합니다.
William Brendel

4
사례 1과 3에 대한 예제가 있습니다. 현재 클래스 인스턴스가 다른 클래스의 메소드에 대한 인수로 사용되는 사례 2의 예제를 제공 할 수 있습니까?
dbconfession

4
@AStar 지난 몇 년 동안 함께 일한 대부분의 Java 코드베이스 this에서 위의 세터 예제와 같이 명확성이 필요한 경우에만 사용됩니다. 코딩 스타일과 "모범 사례"는 요청한 사람에 따라 크게 다를 수 있지만 일반적으로 합리적인 패턴을 선택하고 고수하는 것이 좋습니다. 단일 코드베이스 내부에서도 일관성은 가독성과 유지 관리 측면에서 먼 길을 가고 있습니다.
William Brendel

71

두 번째로 중요한 사용법은 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;
    }
  }
}

46

당신은 사용할 필요가 this- 대부분의 사람들은 그것을 사용 - 같은 이름의 중복 지역 변수있을 때. (예를 들어 세터 메소드)

물론 사용해야 할 또 다른 좋은 이유 this는 IDE에서 인텔리전스가 팝업되기 때문입니다. :)


1
그러나 찾은 후에는 백 스페이스해야합니다. 프로그래밍이 피곤합니다!
LegendLength

25

유일한 필요 를 사용하는 this.다른 현재 범위의 주 내에서 변수와 동일한 이름과 (윌리엄 설명 같은) 인스턴스 멤버를 참조 할 때 규정이다. 그 외에도 x와 사이의 동작에는 차이가 없습니다 this.x.


3
중복 이름이있는 경우 변수 이름 중 하나의 이름이 잘못 지정되므로 이름을 바꿔야합니다. 또는 적어도 이름이 더 나을 수 있습니다.
CaffGeek

3
@Chad : Java setter 메소드에서 일반적입니다. 그러나 setter 메소드 이외의 문장은 일반적으로 유지됩니다.
윌리엄 브렌델

2
this.x코드를 좀 더 명확하게 읽는 데 사용할 수도 있습니다. 코드의 유지 관리 성 / 가독성 또한 고려해야 할 요소입니다.
Bryan Rehbein

1
@ 차드 : 나는 열정적으로 충분히 동의 할 수 없습니다. "주님"이니까요 두 개의 다른 변수에 동일한 이름을 지정할 수 있습니다. 왜 원하십니까?
BlairHippo

2
@ 블레어 : 당신의 대답을 읽으면 당신이 setter 메소드 에서이 연습을 선호하지 않지만 많은 사람들이 그것을 좋아한다는 것이 분명합니다 (나는 그 목록에 자신을 포함시킬 것입니다). 값을 취하는 setter 메소드가있는 경우 전달 된 값은 "new"값이어야하므로 변수 이름에 "new"를 추가하면 공개 API에 불필요한 중복성이 추가되는 것으로 보입니다.
Adam Robinson

15

"this"는 한 생성자를 다른 생성자에서 호출 할 때도 유용합니다.

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

11

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
이것은 내가 검색하고 여기에 올 때 내가 원했던 대답 유형이지만 코드에 대한 설명이 없으므로 "this"에 대해 묻는 대부분의 사람들은 "새 사용자를 반환 (this);" 내가하지 않는 것을 의미합니다 ...
nckbrz

빌더 패턴은 구성시 매개 변수를 명확하게 지정하는 데 사용됩니다. 어떤 문자열이 어떤 문자열인지 쉽게 알 수있는 새로운 사용자 (문자열, 문자열) 대신 새로운 Builder (). setFirstName ( "Jane"). setSurname ( "Smith"). build ()가 있습니다. 이것을 Builder.set ... () 함수에서 반환하여 연결 할 수 있습니다.
ChrisPhoenix

10

좋은 답변이 많이 있지만 this어디에나 두어야 할 또 다른 사소한 이유가 있습니다. 일반 텍스트 편집기 (예 : 메모장 등)에서 소스 코드를 열려고하면 사용 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에디터의 "find"기능을 사용하기 전까지는 어디에 있는지 알아 내기 힘들 것입니다. 그런 다음 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속하고 해당 메소드에 선언 된 로컬 변수 라는 것을 알고 있습니다.Worlds

물론 무언가를 디자인 할 때마다 규칙을 만듭니다. 따라서 API 또는 프로젝트를 디자인 할 때 규칙에 "누군가이 소스 코드를 모두 메모장으로 열면 머리에 직접 촬영해야합니다"라는 규칙이 포함되어 있으면 를 수행하지 않는 것이 좋습니다.


위대한 답변 @Jai
gaurav

촬영해야 할 첫 번째 이유 는 코드가 이미 중첩 될 필요가없는 다른 클래스로 분할 된 경우 몇 개의 10k 줄의 코드로 클래스를 작성하는 것입니다. :
LuCio

@LuCio Lol true xD
Jai

7

변수 이름이 겹치지 않는 한 코드를 읽을 때 명확하게 표시됩니다.


1
this불필요 할 때 키워드를 지속적으로 볼 때 코드가 읽기 어려운 보일러 플레이트 코드 일뿐입니다.
AxeEffect

방금 모든 멤버에게 'this'라는 접두사를 요구하는 오픈 소스 프로젝트를 발견했습니다 . 그 외에도 프로젝트는 매우 잘 쓰여졌지만 나는 그들과 종교 토론을하려고합니다.
LegendLength

4
@ AxeEffect 나는 이것이 정말로 오래되었다는 것을 알고 있지만 ... this코드를 lmao를 읽기가 더 어렵게 만들지는 않습니다.
Xatenev

4

@William Brendel의 답변은 세 가지 사용 사례를 훌륭하게 제공했습니다.

사용 사례 1 :

에 offical 한 자바 문서 페이지에 같은 사용 사례를 제공한다.

인스턴스 메소드 또는 생성자 내에서 이것은 현재 객체 (메소드 또는 생성자가 호출되는 객체)에 대한 참조입니다. 이를 사용하여 인스턴스 메소드 또는 생성자 내에서 현재 오브젝트의 모든 멤버를 참조 할 수 있습니다.

두 가지 예를 다룹니다.

이것을 필드함께 사용하고 생성자와 함께 사용

사용 사례 2 :

이 게시물에서 인용되지 않은 다른 유스 케이스 : this데이터 및 메소드의 중요한 섹션을 보호하기 위해 멀티 스레드 응용 프로그램의 현재 객체를 동기화하는 데 사용할 수 있습니다.

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

사용 사례 3 :

빌더 패턴의 구현은 this수정 된 오브젝트를 리턴하는 데 사용 됩니다.

이 게시물을 참조하십시오

빌더를 별도의 클래스로 유지 (유창한 인터페이스)


2

구글은 썬 사이트에이 페이지를 조금 소개했다.

변수에 대해 옳습니다. this실제로 메소드 필드를 클래스 필드와 구별하는 데 사용할 수 있습니다.

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

그러나 나는 그 협약을 정말로 싫어합니다. 문자 그대로 동일한 이름을 갖는 두 가지 변수를 제공하는 것이 버그의 레시피입니다. 나는 다음과 같은 것을 선호한다.

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

동일한 결과이지만 실수로 x실제로 참조하려고 할 때 실수로 언급하는 버그가 발생 x하지 않습니다.

메소드와 함께 사용하면 효과에 대한 것이 맞습니다. 당신은 그것의 유무에 관계없이 동일한 결과를 얻을 수 있습니다. 사용할 수 있습니까? 확실한. 사용해야합니까? 당신에게 달려 있지만, 개인적으로 명확성이 추가되지 않는 무의미한 세부 묘사라고 생각한다면 (코드가 정적 가져 오기 문으로 가득 차 있지 않은 한), 나는 그것을 직접 사용하지 않을 것입니다.


4
관습이 아니며 프로그램 언어 범위 지정 메커니즘입니다. newX (매개 변수 x에 pX를 선호합니다)를 사용하는 것이 규칙입니다.
Bill K

@ 빌 K : 당신이 만들고있는 차이점을 이해하지 못합니다. 입력 변수 x, newX, pX 또는 mangroveThroatWarblerX의 이름을 지정할 수 있습니다. "new", "p"또는 "Gratuitous Monty Python References"를 앞에 붙인 상태에서 이름을 규칙이 아닌 변수와 동일한 이름으로 지정하는 방법은 무엇입니까?
BlairHippo

3
"Gratuitoud Monty Python References"는 컨벤션이 아니며 LAW입니다.
Adam Robinson

+1 : 우리는 인자와 메소드 변수에 클래스 변수와 다른 명명 표준을 사용합니다. 인수 / 메소드 변수를 약칭하고 클래스 / 인스턴스 변수에 전체 단어를 사용합니다.
Lawrence Dol

1
명명 규칙을 사용하여 해결하는 것은 흠입니다. 언어 기능을 사용하여 문제 해결-언어 기능을 사용하지 않거나 항상 사용하는 것이 관례 일 것입니다 ... 이것을 사용하십시오. 회원에 액세스 할 때마다 컨벤션이됩니다. 그것이 중요하지 않은 것 같아, 나는 이것도 싫어.
Bill K


1

하나의 인스턴스 변수와 동일한 이름의 다른 로컬 변수라는 두 개의 변수가있는 경우이를 사용합니다. 이름 사이의 충돌을 피하기 위해 현재 실행중인 객체를 참조하십시오.


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

0

일부 방법에서 "this.x"대신 "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
     }
  }

"method ()"만 사용하면 기본적으로 현재 객체에 적용되지 않습니까?

예. 그러나 필요한 this.method()경우이 개체가 호출했음을 명확하게합니다.


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
  }

0

에 대하여 윌리엄 브렌델 의 게시물과 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

java의 "This"키워드는 현재 클래스 객체를 참조하는 데 사용됩니다.

자바에는 "this"키워드가 6 가지 있습니다.

  1. 클래스 레벨 변수에 액세스 : 로컬 및 클래스 레벨 변수가 동일한 경우 주로 사용
  2. 클래스 메소드에 액세스 : 이것은 기본 동작이며 무시할 수 있습니다
  3. 같은 클래스의 다른 생성자 를 호출
  4. 'this'키워드 를 반환 값으로 사용 : 메소드에서 현재 인스턴스를 반환
  5. 메소드에 인수로 'this'키워드 전달 Passing : 현재 클래스 인스턴스를 인수로 전달
  6. 이 키워드 를 생성자에 대한 인수로 : 현재 클래스 인스턴스를 인수로 전달합니다.

심판 : https://stacktraceguru.com/java/this-keyword-in-java


-8

현재 개체의 멤버가 사용되도록합니다. 스레드 안전성이 중요한 경우, 일부 응용 프로그램은 잘못된 오브젝트 멤버 값을 변경할 수 있으므로 올바른 오브젝트 멤버 값이 사용되도록 멤버에 적용해야합니다.

객체가 스레드 안전성과 관련이없는 경우 어떤 객체 멤버의 값을 사용할지 지정할 이유가 없습니다.


실제로는 그렇지 않습니다. 나는 당신이 생각하고있는 사건조차 확실하지 않지만, 당신이 말하려는 것을 이해하는 데 도움이 될 수있는 예가 있습니다.
David Berger

1
예. 나는 당신이 설명하는 것이 스레드 안전과 관련이 있다는 것을 알고 있습니다. 스레드 안전과 관련된이 질문에 대한 정답은 없습니다. 올바른 객체를 참조하기 위해 "this"가 필요한 경우 일단 그렇게하면 메서드 나 속성은 동기화 된 경우에만 스레드로부터 안전합니다. 참조가 전혀 모호한 경우 멀티 스레딩이 문제인지 여부는 모호합니다.
David Berger
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.