Nice programing

앞으로 참조 할 때 "this"키워드를 사용해야하는 이유는 무엇입니까?

nicepro 2020. 12. 7. 20:39
반응형

앞으로 참조 할 때 "this"키워드를 사용해야하는 이유는 무엇입니까?


this클래스에서 비 정적 변수에 액세스 하기 위해 키워드를 사용할 때 Java는 오류를 제공하지 않습니다. 그러나 사용하지 않으면 Java에서 오류가 발생합니다. 왜 사용해야 this합니까?

일반적으로를 언제 사용해야하는지 알고 this있지만이 예제는 일반적인 사용과 매우 다릅니다.

예:

class Foo {
//  int a = b; // gives error. why ?
    int a = this.b; // no error. why ?
    int b;
    int c = b;

    int var1 = this.var2; // very interesting
    int var2 = this.var1; // very interesting
}

변수가 먼저 선언 된 다음 할당됩니다. 그 클래스는 다음과 같습니다.

class Foo {
    int a;
    int b;
    int c = b;

    int var1;
    int var2;

    public Foo() {
        a = b;

        var1 = var2;
        var2 = var1;
    }
}

당신이 할 수없는 이유가 int a = b;있기 때문입니다 b아직 오브젝트가 작성 될 때 정의되지 않은,하지만 개체 자체 (즉 this)의 멤버 변수의 모든 존재.

각각에 대한 설명은 다음과 같습니다.

    int a = b; // Error: b has not been defined yet
    int a = this.b; // No error: 'this' has been defined ('this' is always defined in a class)
    int b; 
    int c = b;  // No error: b has been defined on the line before  

전체 설명은 Java 언어 사양의 섹션 8.3.3 : " 필드 초기화 중 전방 참조 "에 있습니다.

정방향 참조 (해당 시점에서 아직 선언되지 않은 변수 참조)는 다음이 모두 참인 경우에만 오류입니다.

  • 클래스 또는 인터페이스 C의 인스턴스 변수 선언은 인스턴스 변수 사용 후 텍스트로 나타납니다.

  • 사용은 C의 인스턴스 변수 이니셜 라이저 또는 C의 인스턴스 이니셜 라이저에서 간단한 이름 입니다.

  • 사용은 과제의 왼쪽에 있지 않습니다.

  • C는 사용을 포함하는 가장 안쪽의 클래스 또는 인터페이스입니다.

굵게 표시된 텍스트 : "사용은 단순한 이름입니다."를 참조하십시오. 단순 이름은 추가 제한이없는 변수 이름입니다. 귀하의 코드에서는 b단순한 이름이지만 this.b그렇지 않습니다.

그런데 왜?

그 이유는 JLS 예제의 필기체 텍스트에 다음과 같이 나와 있기 때문입니다.

"위의 제한 사항은 컴파일 타임에 순환 또는 기타 잘못된 초기화를 포착하도록 설계되었습니다."

즉, this.b자격을 갖춘 참조가 수행중인 작업에 대해 신중하게 생각할 가능성이 더 높다고 생각하기 때문에 허용 하지만 단순히 사용 b한다는 것은 실수를했다는 의미 일 수 있습니다.

이것이 자바 언어 설계자의 근거입니다. 그것이 실제로 사실인지 아닌지는 내가 아는 한 연구되지 않았습니다.

초기화 순서

To expand on the above, in reference to Dukeling's comment on the question, using a qualified reference this.b will likely not give you the results you want.

I'm restricting this discussion to instance variables because the OP only referred to them. The order in which the instance variables are assigned is described in JLS 12.5 Creation of New Class Instances. You need to take into account that superclass constructors are invoked first, and that initializations code (assignments and initialization blocks) are executed in textual order.

So given

int a = this.b;
int b = 2;

you will end up with a being zero (the value of b at the time that a's initializer was executed) and b being 2.

Even weirder results can be achieved if the superclass constructor invokes a method that is overridden in the subclass and that method assigns a value to b.

So, in general, it is a good idea to believe the compiler and either reorder your fields or to fix the underlying problem in case of circular initializations.

If you need to use this.b to get around the compiler error, then you're probably writing code that will be very hard to maintain by the person after you.


You have presented 3 cases:

  1. int a = b; int b;
    This gives error because the compiler will look for b in the memory and it will not be there. but when you use this keyword then it specifies explicitly that the b is defined in the scope of the class, all class references will be looked up for it, and finally it will find it.
  2. Second scenario is pretty simple and as I described, b is defined in the scope before c and will not be a problem while looking for b in the memory.
  3. int var1 = this.var2;
    int var2 = this.var1;
    In this case no error because in each case the variable is defined in the class and assignment uses this which will look for the assigned variable in the class, not just the context it is followed by.

For any class in Java this is a default reference variable (when no specific reference is given) that either user can give or the compiler will provide inside a non-static block. For example

public class ThisKeywordForwardReference {

    public ThisKeywordForwardReference() {
        super();
        System.out.println(b);
    }

    int a;
    int b;

    public ThisKeywordForwardReference(int a, int b) {
        super();
        this.a = a;
        this.b = b;
    }

}

You said that int a = b; // gives error. why ? gives compile time error because b is declared after a which is an Illegal Forward Reference in Java and considered as a compile-time error.

But in the case of methods Forward Reference becomes legal

int a = test();
int b;

int test() {
    return 0;
}

But in my code, the constructor with the argument is declared before both a & b, but not giving any compile-time error, because System.out.println(b); will be replaced by System.out.println(this.b); by the compiler.

The keyword this simply means current class reference or the reference on which the method, constructor or the attribute is accessed.

A a1 = new A();  // Here this is nothing but a1
a1.test();  // Here this is again a1

When we say a = this.b; it is specifying that b is a current class attribute, but when we say a = b; since it is not inside a non-static block this won't be present and will look for an attribute declared previously which is not present.


Please look at the Java Language Specification: https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.2.3

This is the reason, IMO: The usage is via a simple name.

So in this case you have to specify the name using this.

참고URL : https://stackoverflow.com/questions/46967759/why-must-i-use-the-this-keyword-for-forward-references

반응형