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.