program story

Java가 컴파일 타임에 변수를 바인드하는 이유는 무엇입니까?

inputbox 2020. 11. 25. 07:55
반응형

Java가 컴파일 타임에 변수를 바인드하는 이유는 무엇입니까?


다음 예제 코드를 고려하십시오.

class MyClass {
    public String var = "base";

    public void printVar() {
        System.out.println(var);
    }
}

class MyDerivedClass extends MyClass {
    public String var = "derived";

    public void printVar() {
        System.out.println(var);
    }
}

public class Binding {
    public static void main(String[] args) {
        MyClass base = new MyClass();
        MyClass derived = new MyDerivedClass();

        System.out.println(base.var);
        System.out.println(derived.var);
        base.printVar();
        derived.printVar();
    }
}

다음 출력을 제공합니다.

base
base
base
derived

메서드 호출은 런타임에 해결되고 올바른 재정의 된 메서드가 예상대로 호출됩니다.
변수 액세스는 나중에 배웠 듯이 컴파일 타임에 해결됩니다. 나는 다음과 같은 출력을 기대하고 있었다.

base
derived
base
derived

파생 클래스에서 var그림자의 재정의 는 기본 클래스 그림자 이기 때문입니다 .
변수 바인딩이 런타임이 아닌 컴파일 타임에 발생하는 이유는 무엇입니까? 이것은 성능상의 이유 일 뿐입니 까?


그 이유는 아래 인용 섹션 15.11 의 예에서 Java 언어 사양에 설명되어 있습니다.

...

마지막 줄은 실제로 액세스되는 필드가 참조 된 개체의 런타임 클래스에 종속되지 않음을 보여줍니다. 하더라도 s클래스의 오브젝트에 대한 참조를 보유하고 T,식이 s.x받는 지칭 x클래스 필드 S표현식의 타입 때문 s이다 S. 클래스 T의 객체에는라는 두 개의 필드가 있습니다 x. 하나는 클래스 용 T이고 다른 하나는 수퍼 클래스 용 S입니다.

이러한 필드 액세스에 대한 동적 조회가 없기 때문에 프로그램을 직접 구현하여 효율적으로 실행할 수 있습니다. 후기 바인딩 및 재정의 기능을 사용할 수 있지만 인스턴스 메서드가 사용되는 경우에만 ...

그렇습니다. 성능이 이유입니다. 필드 액세스식이 평가되는 방식에 대한 사양은 다음과 같습니다.

  • 필드가 아닌 경우 static:

    ...

    • 필드가 공백이 아닌 final경우 결과는 PrimaryT 값이 참조하는 객체에서 찾은 유형의 명명 된 멤버 필드 값입니다 .

여기서 귀하의 경우는 변수를 참조 derived타입이다 MyClass.

@Clashsoft가 제안한 또 다른 이유는 하위 클래스에서 필드가 재정의되지 않고 숨겨 지기 때문 입니다. 따라서 선언 된 유형 또는 캐스트를 사용하여 액세스 할 필드를 허용하는 것이 합리적입니다. 이것은 정적 메서드에서도 마찬가지입니다. 이것이 필드가 선언 된 유형에 따라 결정되는 이유입니다. 실제 유형에 따라 달라지는 인스턴스 메서드로 재정의하는 것과는 다릅니다. 위의 JLS 인용문은 실제로 이러한 이유를 암시 적으로 언급합니다.

The power of late binding and overriding is available, but only when instance methods are used.


While you might be right about performance, there is another reason why fields are not dynamically dispatched: You wouldn't be able to access the MyClass.var field at all if you had a MyDerivedClass instance.

Generally, I don't know about any statically typed language that actually has dynamic variable resolution. But if you really need it, you can make getters or accessor methods (which should be done in most cases to avoid public fields, anyway):

class MyClass
{
    private String var = "base";

    public String getVar() // or simply 'var()'
    {
        return this.var;
    }
}

class MyDerivedClass extends MyClass {
    private String var = "derived";

    @Override
    public String getVar() {
        return this.var;
    }
}

The polymorphic behaviour of the java language works with methods and not member variables: they designed the language to bind member variables at compile time.


In java, this is by design. Because, the set up of fields to be dynamically resolved would make things to run a bit slower. And in real, there's not any reason of doing so. Since, you can make your fields in any class private and access them with methods which are dynamically resolved.

So, fields are made to resolved better at compile time instead :)

참고URL : https://stackoverflow.com/questions/32422923/why-does-java-bind-variables-at-compile-time

반응형