Java에서 null은 무엇입니까?


252

무엇입니까 null?

null아무것도의 인스턴스는?

어떤 세트에 null속합니까?

메모리에 어떻게 표현됩니까?


yegor256. JLS에서 null 정보 "널 리터럴. 널 유형에는 널 문자 널로 표시되는 널 참조 인 하나의 값이 있으며 ASCII 문자로 구성됩니다. 널 리터럴은 항상 널 유형입니다." 기사의 요점에 대해. '변경 가능하고 불완전한 개체'는 기능입니다. '천천히 실패'는 의도적으로 설계된 능력입니다. '컴퓨터 사고 대 객체 사고'는 단지 두 가지 사고 방식입니다. '모호한 의미 론적'은 너무 주관적입니다. '임시 오류 처리'는 오류 작업의 또 다른 유형입니다. Null은 리터럴이거나 JLS에 지정된 다른 것입니다.
Oleksii Kyslytsyn

답변:


310

null은 무엇인가의 인스턴스입니까?

아니, 형이없는 null됩니다 instanceof.

15.20.2 타입 비교 연산자 instanceof

RelationalExpression:
    RelationalExpression instanceof ReferenceType

런타임시, instanceof연산자 의 결과 trueRelationalExpression 의 값 이 아니고 참조 를 a를 올리지 않고 ReferenceTypenull 으로 캐스트 할 수있는 경우 입니다. 그렇지 않으면 결과는 입니다.ClassCastExceptionfalse

이 방법이 모든 유형 ER어떤을위한, E o, o == null, o instanceof R항상 false.


'null'은 어떤 세트에 속합니까?

JLS 4.1 종류와 값의 종류

이름이없는 특별한 null 유형 인 expression 유형 null도 있습니다. 때문에 유형 이름이없는,의 변수를 선언하는 것은 불가능 받는 형식이나 주조에 유형입니다. null레퍼런스의 표현의 유일하게 가능한 값 타입. null참조는 항상 참조 형식으로 캐스팅 할 수 있습니다. 실제로 프로그래머는 유형을 무시하고 null참조 유형일 수있는 특수 리터럴 인 것처럼 가장 할 수 있습니다.


널이란 무엇입니까?

위의 JLS 인용문에서 알 수 있듯이 실제로는 단순히 "모든 참조 유형이 될 수있는 특수 리터럴"인 것처럼 가장 할 수 있습니다.

Java에서는 null == null(다른 언어에서는 항상 그런 것은 아닙니다). 계약에 따라 다음과 같은 특수 속성도 있습니다 java.lang.Object.

public boolean equals(Object obj)

임의의 비를 들어 null기준값 x, x.equals(null)해야한다 return false.

모든 참조 유형에 대한 기본값 이기도합니다 (변수가있는 변수의 경우).

JLS 4.12.5 변수의 초기 값

  • 각 클래스 변수, 인스턴스 변수 또는 배열 구성 요소 는 작성 될 때 기본값으로 초기화됩니다 .
    • 모든 참조 유형의 기본값은 null입니다.

이것이 사용되는 방법은 다양합니다. 이 필드를 사용하여 필드의 초기 초기화 ( lazy initialize ) 필드 를 활성화 할 수 있습니다 . 필드는 null실제로 사용될 때까지 초기 값을 가지며 "실제"값 (계산 비용이 많이들 수 있음)으로 대체됩니다.

다른 용도도 있습니다. 실제 사례를 보자 java.lang.System.

public static Console console()

결과 : 시스템 콘솔 (있는 경우), 그렇지 않은 경우 null.

이것은 매우 일반적인 사용 패턴 null입니다. 객체가 존재하지 않음을 나타내는 데 사용됩니다.

다음은 또 다른 사용법 예입니다 java.io.BufferedReader.

public String readLine() throws IOException

리턴 : String행의 내용을 포함하고 행 종료 문자를 포함하지 않거나 null스트림의 끝에 도달 한 경우

그래서 여기에, readLine()반환 instanceof String은 마지막으로 반환 될 때까지, 각 라인 null의 끝을 의미 할 수 있습니다. 이를 통해 다음과 같이 각 줄을 처리 할 수 ​​있습니다.

String line;
while ((line = reader.readLine()) != null) {
   process(line);
}

종료 조건이 readLine()returning에 의존하지 않도록 API를 디자인 할 수 null있지만이 디자인은 간결하게 만드는 이점이 있음을 알 수 있습니다. 빈 줄 때문에 빈 줄에는 문제가 없습니다 "" != null.

이번에는 java.util.Map<K,V>다음 에서 또 다른 예를 보자 .

V get(Object key)

지정된 키가 맵핑 된 값을 리턴하거나이 null맵에 키에 대한 맵핑이없는 경우 값을 리턴합니다 .

이 맵이 null값을 허용하는 경우 , 리턴 값이 null반드시 맵에 키에 대한 맵핑이 없음을 나타내는 것은 아닙니다. 지도가 키를에 명시 적으로 매핑 할 수도 있습니다 null. containsKey작업은이 두 경우를 구별 할 수 있습니다.

여기에서 사용 null이 어떻게 복잡해질 수 있는지 알아보기 시작합니다 . 첫 번째 문장은 키가 매핑되지 않으면 null반환 된다고 말합니다 . 두 번째 문은 키가 매핑 된 경우에도 있다고 null할 수 반환.

반대로, 키와 값을 java.util.Hashtable허용하지 않으면 서 일을 더 단순하게 유지 null합니다. its V get(Object key)가 반환 null되면 키가 매핑되지 않았 음을 의미합니다.

나머지 API를 읽고 null사용되는 위치와 방법을 찾을 수 있습니다. 이들이 항상 모범 사례 는 아니라는 점을 명심하십시오 .

일반적으로 말하자면 null다음을 의미하는 특수한 값으로 사용됩니다.

  • 초기화되지 않은 상태
  • 종료 조건
  • 존재하지 않는 개체
  • 알 수없는 값

메모리에 어떻게 표현됩니까?

자바? 걱정하지 마십시오. 그렇게하는 것이 가장 좋습니다.


null좋은 가요 ?

이것은 이제 경계 주관적입니다. 어떤 사람들 null은 많은 프로그래머 오류를 피할 수 있다고 말합니다 . 어떤 사람들은 NullPointerException자바처럼 잡는 언어에서는 프로그래머 오류로 실패 할 것이므로 사용하는 것이 좋다고 말합니다. 어떤 사람들 nullNull 객체 패턴 등 을 사용하여 피 합니다 .

이것은 자체적으로 큰 주제이므로 다른 질문에 대한 답변으로 가장 잘 논의됩니다.

나는 이것을 null자신 의 발명가 인 CAR Hoare (Quicksort Fame) 의 인용으로 인용 할 것이다 :

나는 그것을 10 억 달러의 실수라고 부릅니다. 그것은 null1965 년에 참조 의 발명이었다 . 그때, 나는 객체 지향 언어 (ALGOL W)로 참조를위한 최초의 포괄적 인 타입 시스템을 설계하고 있었다. 필자의 목표는 컴파일러가 자동으로 검사를 수행하여 모든 참조 사용이 절대적으로 안전하도록하는 것이 었습니다. 그러나 null구현하기가 쉽기 때문에 참조를 하려는 유혹에 저항 할 수 없었습니다 . 이로 인해 수많은 오류, 취약성 및 시스템 충돌이 발생했으며, 이는 아마도 지난 40 년 동안 수십억 달러의 고통과 피해를 야기했을 것입니다.

이 프리젠 테이션비디오 는 더 깊어집니다. 추천 시계입니다.


4
NIL1960 년 에 LISP에는 null 참조가 있었으며 아마도 초기에는있었습니다. 그러나 Hoare가 실제로 그 인용에서 null 참조의 발명을 주장하려고 한다고 생각하지 않습니다 .
Stephen C

7
Hoare는 null 참조의 발명을 주장하려고 시도하지 않습니다. 그는 단지 그들이 영향력있는 곳에서 그것들을 이용할 수있게 만들었다 고 주장하고있을뿐입니다. Java를 포함하여 Algol에서 영감을 얻은 많은 언어가 있으며, Null 참조의 사용이 Algol에서 부분적으로 영감을 얻거나 복사 된 경우 Hoare는 이러한 비용에 대한 책임을집니다. 그러나 나는 그의 추정치가 다소 낮다고 생각합니다. 1 조 달러는 실제 비용에 더 가깝습니다.
cjs

32

null은 무엇인가의 인스턴스입니까?

아닙니다. 그것이 모든 수업에 대해 null instanceof X돌아 오는 이유 입니다 . ( 유형이 객체 유형 인 변수에 할당 할 수 있다는 사실에 속지 마십시오 . 엄밀히 말하면, 할당에는 암시 적 유형 변환이 포함됩니다 (아래 참조).falseXnull

'null'은 어떤 세트에 속합니까?

널 유형이 유일하고 유일한 널 유형이며, 여기서 널 유형은 다음과 같이 정의됩니다.

"특정 널 유형, 즉 표현식 널의 유형은 이름이 없습니다. 널 유형에는 이름이 없기 때문에 널 유형의 변수를 선언하거나 널 유형으로 캐스트 할 수 없습니다. 참조는 null 유형의 표현식에서 유일하게 가능한 값입니다 .null 참조는 항상 모든 참조 유형으로 캐스트 될 수 있습니다. 실제로 프로그래머는 널 유형을 무시하고 null이 단지 임의의 특수 리터럴 인 것처럼 가장 할 수 있습니다. 참조 유형. " JLS 4.1

널이란 무엇입니까?

위 참조. 일부 상황에서 null"개체 없음"또는 "알 수 없음"또는 "사용할 수 없음"을 나타내는 데 사용되지만 이러한 의미는 응용 프로그램에 따라 다릅니다.

메모리에 어떻게 표현됩니까?

그것은 구현 null에 따라 다르며 순수한 Java 프로그램 에서는 표현을 볼 수 없습니다 . (그러나 null모든 Java 구현은 아니지만 대부분의 경우 0의 기계 주소 / 포인터로 표시됩니다.)


14

널이란 무엇입니까?

아무것도 아니다.

null은 무엇인가의 인스턴스입니까?

그것은 아무것도 아니기 때문에 그것은 아무것도 인스턴스가 될 수 없습니다.

null은 어떤 집합에 속합니까?

어떤 세트도 없습니다

메모리에 어떻게 표현됩니까?

일부 참조가 다음을 가리키는 경우 :

Object o=new Object();

힙 메모리에서 새로 작성된 오브젝트에 할당 된 공간이 있습니다. 그리고 o는 ​​메모리에서 할당 된 공간을 가리 킵니다.

지금 o=null;

이것은 이제 o가 객체의 메모리 공간을 가리 키지 않음을 의미합니다.


1
"이제 o = null입니다. 이제 o는 객체의 메모리 공간을 가리 키지 않습니다." 가비지 콜렉션이 JAVA에서 작동하는 방식이라고 생각합니다.
Hardik Mishra

9

아니요, 인스턴스가 아닙니다. instanceof는 항상 거짓입니다.



6

Null은 어떤 클래스의 인스턴스도 아닙니다.

그러나 (객체 또는 배열) 유형의 변수에 null을 할당 할 수 있습니다.

 // this is false   
 boolean nope = (null instanceof String);

 // but you can still use it as a String
 String x = null;
 "abc".startsWith(null);

6

Java에서 널 (tm)

C 및 C ++에서 "NULL"은 헤더 파일에 정의 된 상수이며 다음과 같은 값을 갖습니다.

    0

또는:

    0L

또는:

    ((void*)0)

컴파일러 및 메모리 모델 옵션에 따라 다릅니다. NULL은 C / C ++ 자체의 일부가 아닙니다.

Java (tm)에서 "null"은 키워드가 아니라 널 유형의 특수 리터럴입니다. int 또는 boolean과 같은 기본 유형으로 변환 할 수 없지만 모든 참조 유형으로 캐스트 할 수 있습니다. 널 리터럴은 반드시 0 값을 가질 필요는 없습니다. 그리고 널 유형으로 캐스트하거나이 유형의 변수를 선언하는 것은 불가능합니다.


5

바이트 코드 표현

Java null는 직접 JVM을 지원합니다.이를 구현하기 위해 세 가지 명령이 사용됩니다.

  • aconst_null:이 예에 변수를 설정 null마찬가지로Object o = null;
  • ifnullifnonnull:에 개체를 비교 예 null에서와 같이if (o == null)

6 장 "Java Virtual Machine 명령어 세트"null다른 명령어에 미치는 영향에 대해 언급 NullPointerException합니다.

2.4. "참조 유형 및 값" 은 다음 null과 같은 일반적인 용어로 언급 됩니다.

참조 값은 특수 null 참조 일 수도 있습니다. 여기서 개체가없는 참조는 여기에서 null로 표시됩니다. null 참조는 초기에 런타임 유형이 없지만 모든 유형으로 캐스트 될 수 있습니다. 참조 유형의 기본값은 널입니다.


4

null특별한 가치이며 어떤 것도 아닙니다. 분명히 이유는 instanceof아무것도 될 수 없습니다 .


3

null클래스의 인스턴스가 아닌 특수 값입니다. 이것은 다음 프로그램에 의해 설명됩니다.

public class X {
   void f(Object o)
   { 
      System.out.println(o instanceof String);   // Output is "false"
   }
   public static void main(String[] args) {
      new X().f(null);
   }
}

6
예제에서 보여주는 유일한 것은 null의 인스턴스가 아니라는 것입니다 String.
Sasha Chedygov

4
서명을로 변경하면 void f(String o)더 의미가 있습니다.
Thilo

2

Java의 null은 C ++의 nullptr과 비슷하거나 비슷합니다.

C ++의 프로그램 :

class Point
{
    private:
       int x;
       int y;
    public:
       Point(int ix, int iy)
       {
           x = ix;
           y = iy;
       }
       void print() { std::cout << '(' << x << ',' << y << ')'; }
};
int main()
{
    Point* p = new Point(3,5);
    if (p != nullptr)
    {
       p->print();
       p = nullptr;
    }
    else
    {
        std::cout << "p is null" << std::endl;
    }
    return 0;
}

자바에서 동일한 프로그램 :

public class Point {
    private int x;
    private int y;
    public Point(int ix, int iy) {
        x = ix;
        y = iy;
    }
    public void print() { System.out.print("(" + x + "," + y + ")"); }
}
class Program
{
    public static void main(String[] args) {
        Point p = new Point(3,5);
        if (p != null)
        {
            p.print();
            p = null;
        }
        else
        {
            System.out.println("p is null");
        }
    }
}

이제 위의 코드에서 Java의 null이 무엇인지 이해합니까? 그렇다면 C / C ++에서 포인터를 배우는 것이 좋습니다. 그러면 이해할 것입니다.

C에서 C ++와 달리 nullptr은 정의되지 않았지만 대신 NULL이 사용되며 C ++에서도 사용될 수 있지만 C ++에서 NULL은 항상 포인터와 관련이 있기 때문에 NULL보다 더 선호됩니다. 따라서 C ++에서 접미사 "ptr"은 단어 끝에 추가되었으며 모든 문자는 이제 소문자이지만 중요하지 않습니다.

Java에서는 기본이 아닌 클래스 유형의 모든 변수가 항상 해당 유형의 객체를 참조하거나 상속되며 null은 null 클래스 객체 참조이지만 null 포인터는 아닙니다. Java에는 "포인터"가 없기 때문에 클래스에 대한 참조가 있기 때문입니다. 객체는 대신 사용되며 Java의 null은 클래스 객체 참조와 관련이 있으므로 "nullref"또는 "nullrefobj"라고도 할 수 있지만이 길이는 길기 때문에 "null"이라고합니다.

C ++에서는 선택적 멤버 / 변수, 즉 값이없는 멤버 / 변수에 포인터와 nullptr 값을 사용할 수 있습니다. 값 이 없으면 nullptr과 같습니다. 예를 들어 Java의 null을 사용할 수 있습니다.


1

Java에는 두 가지 주요 범주 유형 인 기본참조가 있습니다. 프리미티브 유형으로 선언 된 변수는 값을 저장합니다. 참조 유형 저장소 참조로 선언 된 변수

String x = null;

이 경우 초기화 명령문은 변수“x”를 선언합니다. "x"는 문자열 참조를 저장합니다. 그것은이다 여기. 우선, null은 유효한 객체 인스턴스가 아니므로 할당 된 메모리가 없습니다. 단순히 객체 참조가 객체를 참조하고 있지 않음을 나타내는 값입니다.


0

내 의견으로는 자바에서 null을 보는 흥미로운 방법은 정보의 부재를 나타내지 않고 단순히 모든 유형의 참조에 할당 할 수있는 리터럴 값으로 보는 것입니다. 정보가 없다고 생각하면 a1 == a2가 true라는 것은 실제로 모든 객체를 가리킬 수 있으므로 의미가 없습니다 (둘 다 null 값이 할당 된 경우). 어떤 객체를 가리켜 야하는지 모르겠다.) 그런데 null == null은 java에서 true를 반환합니다. 예를 들어 Java가 SQL : 1999와 같으면 null = = null은 알 수없는 값을 반환합니다 (SQL : 1999의 부울 값은 세 가지 값을 취할 수 있습니다 : true, false 및 unknown이지만 실제로는 unknown은 실제 시스템에서 null로 구현됩니다) ... http://en.wikipedia.org/wiki/SQL


0

JLS에서 공식적으로 모든 질문에 대답하는 짧고 정확한 답변 :

3.10.7. 널 리터럴

널 유형에는 널 문자 널로 표시되는 널 참조 인 ASCII 값으로 구성된 하나의 값이 있습니다.

널 리터럴은 항상 널 유형입니다.

널에 지정된 유형의 참조 만 할당됩니다. 참조에 값 (객체)을 할당하지 않습니다. 이러한 할당은 JVM이 참조하는 양과 할당 할 메모리 영역에 따라 다릅니다.

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