Java의 널 참조에 대한 정적 필드


119

staticJava의 멤버 ( static필드 또는 static메서드)는이 클래스의 개체가 아닌 해당 클래스와 연결됩니다. 다음 코드는 null참조 의 정적 필드에 액세스를 시도합니다 .

public class Main
{
    private static final int value = 10;

    public Main getNull()
    {
        return null;
    }

    public static void main(String[] args)
    {
        Main main=new Main();
        System.out.println("value = "+main.getNull().value);
    }
}

main.getNull()반환 하지만 null작동하고 표시합니다 value = 10. 이 코드는 어떻게 작동합니까?



4
재미를 위해 시도해보십시오 Main main = null; main.getNull().value.
Marko Topolnik 2012

1
이것은 new Thread[]{}[-1].sleep(10);sleep ()이 정적 메소드 인 곳을 상기시켜줍니다 . 이것은 일부 이전 Java 버전에서 성공했습니다.
hertzsprung

답변:


93

해당 동작은 Java 언어 사양에 지정되어 있습니다 .

null 참조를 사용하여 예외를 발생시키지 않고 클래스 (정적) 변수에 액세스 할 수 있습니다.

자세한 내용 은 다음 과 같이 작동 하는 정적 필드 평가입니다Primary.staticField (강조 내)-귀하의 경우 Primary = main.getNull():

  • Primary식이 평가되고 결과가 삭제됩니다 . [...]
  • 필드가 공백이 아닌 최종 필드 인 경우 결과는 기본 표현식의 유형 인 클래스 또는 인터페이스에 지정된 클래스 변수의 값입니다. [...]

5
이 선택이 이루어진 이유 에 대한 정보가있는 사람은 흥미로울 것입니다.

6
@JonofAllTrades 나는 이것이 명백하다고 생각한다. 메소드가 정적이기 때문에 중요하지 않기 때문에 null 참조를 호출 할 때 예외를 던지지 않는 것이 합리적이다.
Malcolm

13
@JonofAllTrades : 진짜 질문은 왜 정적 멤버가 인스턴스로 호출되도록 허용하는 선택이 만들어 졌는가입니다 ... 나에게 그것은 혼란과 덜 읽기 쉬운 코드로 이어질 뿐인 것 같습니다.
Falanwe 2012-07-24

2
@Falanwe : 동의합니다. 저는 거의 허용되지 않는 .NET에서 작업하지만 필요하지 않은 구조입니다. 부모 클래스에 대한 참조가 주어지면 하위 클래스의 적절한 정적 메서드를 호출하고 싶을 것 같습니다.

8
@Falanwe 이것은 허용되지만 Eclipse에서 "정적 필드 Main.value는 정적 방식으로 액세스해야합니다"라는 경고를 발생시킵니다. (나와 같은) 경고에 대해 까다로운 사람들은 그러한 코드를 피할 것입니다.
Artyom

19

말했듯이 정적 필드는 인스턴스와 연결되지 않기 때문입니다.

인스턴스 참조에서 정적 필드에 액세스하는 기능 (현재 수행중인 작업)은 단지 구문상의 설탕이며 추가 의미가 없습니다.
코드가 다음과 같이 컴파일됩니다.

main.getNull(); 
Main.value

7
나는 더 많은 구문 톱밥처럼, 문법 설탕을 부를 것이다)
스티븐 Swensen

3

컴파일 타임에 객체가있는 정적 변수 또는 메서드에 액세스 할 때마다 클래스 이름으로 변환됩니다. 예 :

Main main = null;
System.out.println(main.value);

컴파일시 정적 변수 값의 값을 출력합니다.

System.out.println(Main.value);

증명:

decompiler를 다운로드하고 .class 파일을 .java 파일로 Decompile하면 모든 정적 메소드 또는 변수 참조 객체 이름이 자동으로 클래스 이름으로 대체되는 것을 볼 수 있습니다.


3
  1. static클래스 이름 으로 멤버에 액세스하는 것은 합법적이지만 static개체 참조 변수를 사용하여 멤버에 액세스 할 수 없다는 내용이 작성되지 않았습니다 . 여기에서 작동합니다.

  2. null객체 참조 변수는 액세스 할 수 있습니다 static컴파일 또는 런타임에 예외 중 하나를 throw하지 않고 클래스 변수를.


2

정적 변수와 메서드는 항상 클래스에 속합니다. 그래서 우리가 어떤 객체를 만들 때마다 비 정적 변수와 메소드는 객체와 함께 힙으로 이동하지만 정적은 클래스와 함께 메소드 영역에 상주합니다. 그렇기 때문에 정적 변수 또는 메서드에 액세스하려고 할 때마다 클래스 이름 도트 변수 또는 메서드 이름으로 변환되었습니다.

자세한 내용은 아래 링크를 참조하십시오.

http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.