programing

초기화되지 않은 지역 변수를 사용하여 해당 변수 유형의 정적 콘텐츠에 액세스 할 수없는 이유는 무엇입니까?

nasanasas 2020. 11. 5. 08:08
반응형

초기화되지 않은 지역 변수를 사용하여 해당 변수 유형의 정적 콘텐츠에 액세스 할 수없는 이유는 무엇입니까?


초기화되지 않은 지역 변수 x를 통해 정적 필드에 액세스하는 동안 컴파일 오류가 발생 합니다.Foo foo; foo.xVariable 'foo' might not have been initialized

class Foo{
    public static int x = 1;

    public static void main(String[] args) {
        Foo foo;
        System.out.println(foo.x); // Error: Variable 'foo' might not have been initialized
    }
}

이 오류는 의미가 있는 것처럼 보일있지만static 멤버 에 액세스하기 위해 컴파일러는 실제로 변수 사용하지 않고 해당 유형사용 한다는 사실을 깨닫기 전까지 만 가능 합니다 .

예를 들어 foo값으로 초기화 하면 문제없이 null액세스 x할 수 있습니다.

Foo foo = null;
System.out.println(foo.x); //compiles and while running prints 1!!! 

이러한 시나리오는 컴파일러가 그것이 x정적 임을 인식하고 foo.x작성된 것처럼 처리 하기 때문에 작동 합니다 Foo.x(적어도 지금까지 생각했던 것입니다).

그렇다면 컴파일러는 왜 갑자기 그 장소에서 사용하지 않을foo 가지고 있다고 주장 합니까?

(면책 조항 : 이것은 실제 응용 프로그램에서 사용되는 코드가 아니라 Stack Overflow에서 답을 찾을 수없는 흥미로운 현상 일 뿐이므로 질문하기로 결정했습니다.)


§15.11. 필드 액세스 표현식 :

필드가 정적 인 경우 :

Primary식이 평가되고 결과가 삭제됩니다 . Primary 식의 평가가 갑자기 완료되면 같은 이유로 필드 액세스식이 갑자기 완료됩니다.

이전에는 필드 액세스가 Primary.Identifier.

이것은를 사용하지 않는 것처럼 보이지만 Primary여전히 평가되고 결과가 삭제되므로 초기화해야 함을 보여줍니다. 이는 견적서에 명시된대로 평가가 액세스를 중지 할 때 차이를 만들 수 있습니다.

편집하다:

다음은 Primary결과가 삭제 되더라도가 평가 되는 것을 시각적으로 보여주는 간단한 예 입니다.

class Foo {
    public static int x = 1;

    public static Foo dummyFoo() throws InterruptedException {
        Thread.sleep(5000);
        return null;
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println(dummyFoo().x);
        System.out.println(Foo.x);
    }
}

여기서는 항상 버려지 값을 반환하더라도 5 초 지연 dummyFoo()되기 때문에 여전히 평가 되는 것을 볼 수 있습니다 .printThread.sleep()null

표현식이 평가되지 않은 경우는 print클래스가 때 볼 수있는, 즉시 나타납니다 Foo액세스에 직접 사용 x으로 Foo.x.

참고 : 메서드 호출은 §15.8 Primary Expressions에Primary 표시된 것으로 간주됩니다 .


16 장. 명확한 할당

각 지역 변수 (§14.4) 및 모든 빈 최종 필드 (§4.12.4, §8.3.1.2) 에는 해당 값에 대한 액세스가 발생할 때 확실히 할당 된 값이 있어야합니다.

지역 변수를 통해 무엇 에 액세스하려고 하는지 는 중요하지 않습니다 . 규칙은 그 전에 확실히 할당되어야한다는 것입니다.

필드 액세스 식 을 평가하려면 foo.x해당 primary부분 ( foo)을 먼저 평가해야합니다. 에 대한 액세스 foo가 발생하여 컴파일 타임 오류가 발생 함을 의미합니다 .

지역 변수 또는 빈 마지막 필드 x에 대한 모든 액세스에 대해 액세스 전에 x를 확실히 할당해야합니다. 그렇지 않으면 컴파일 타임 오류가 발생합니다.


규칙을 가능한 한 단순하게 유지하는 것이 가치가 있으며 "초기화되지 않았을 수도있는 변수를 사용하지 마십시오"는 매우 간단합니다.

요컨대, 정적 메소드를 호출하는 확립 된 방법이 있습니다. 항상 변수가 아닌 클래스 이름을 사용하십시오.

System.out.println(Foo.x);

변수 "foo"는 제거해야하는 원치 않는 오버 헤드이며, 컴파일러 오류 및 경고가이를 유도하는 데 도움이 될 수 있습니다.


다른 답변은 일어나는 일의 메커니즘을 완벽하게 설명합니다. 아마도 당신은 Java의 사양에 대한 근거를 원했을 수도 있습니다. Java 전문가가 아니므로 원래 이유를 설명 할 수는 없지만이 점을 지적하겠습니다.

  • Every piece of code either has a meaning or it triggers a compilation error.
  • (For statics, because an instance is unnecessary, Foo.x is natural.)
  • Now, what shall we do with foo.x (access through instance variable)?
    • It could be a compilation error, as in C#, or
    • It has a meaning. Because Foo.x already means "simply access x", it is reasonable that the expression foo.x has a different meaning; that is, every part of the expression is valid and access x.

Let's hope someone knowledgeable can tell the real reason. :-)

참고URL : https://stackoverflow.com/questions/57964026/why-cant-we-use-uninitialized-local-variable-to-access-static-content-from-type

반응형