Czy null jest obiektem?


119

Czy null an Objectw Javie?


41
Nie, nie jest, a dla tych, którzy zastanawiają się, dlaczego takie pytanie, są języki, w których null jest rzeczywiście przedmiotem jak każdy, na przykład Ruby.
JRL

7
W Scali, która jest bardzo drobiazgowa co do typów, istnieje typ Null( właściwie cecha ) mający tylko jedną instancję null.
Carl Smotricz

1
@JRL: Tak z ciekawości, zastanawiam się, jak to wpływa na działanie JRuby ... (nie jestem wystarczająco zaznajomiony z tym poziomem implementacji, aby być pewnym).
Benjamin Oakes

Aby dodać do komentarza @ JRL - szorstki odpowiednik nullto Ruby nil, który jest instancją NilClass
Eliot Sykes

Lub javascript, w którym null instanceof Objectjest fałsz, ale typeof(null)zwraca 'object'. Czy w takim razie jest to przedmiot? Kto wie.
Don Hatch

Odpowiedzi:


166

Gdyby null był obiektem, obsługiwałoby metody java.lang.Objecttakie jak equals(). Jednak tak nie jest - każde wywołanie metody dla wartości null powoduje utworzenie pliku NullPointerException.

Oto, co na ten temat ma do powiedzenia specyfikacja języka Java :

Istnieje również specjalny typ null, typ wyrażenia null, który nie ma nazwy. Ponieważ typ null nie ma nazwy, nie można zadeklarować zmiennej typu null ani rzutować na typ null. Odwołanie o wartości null jest jedyną możliwą wartością wyrażenia typu null. Odwołanie o wartości null można zawsze rzutować na dowolny typ odwołania. W praktyce programista może zignorować typ null i po prostu udawać, że null jest tylko specjalnym literałem, który może być dowolnego typu referencyjnego.

Myślę, że można to sprowadzić do stwierdzenia, że ​​„zero jest wyjątkowe”.


1
Zatem obiekt w Javie jest obiektem tylko wtedy, gdy jest równy lub podklasy java.lang.Object. Praktycznie - tak. Nie możesz stworzyć klasy, która nie jest podklasą java.lang.Object, ale nigdy nie myślałem o tym z bardziej filozoficznego punktu widzenia
Andreas Dolk

Co ciekawe, dokumentacja API dlaNullPointerException wspomina o » nullobiekcie«… :) Ale z drugiej strony można było również mówić o »zerowych wskaźnikach«…
Lumi

Powiedziałeś: „Odniesienie zerowe może być zawsze rzutowane na dowolny typ odniesienia”. Czy możemy więc zwrócić wartość null (typecasted-if allowed) w metodzie z typem odwołania do obiektu (zwracanego)?
Srichakradhar

1
@Srichakradhar: tak, możemy! Które możesz dowiedzieć się łatwiej, wypróbowując to w kodzie, niż pytając tutaj.
Michael Borgwardt,

1
„Odniesienie zerowe jest jedyną możliwą wartością wyrażenia typu null”. Czas przeczytać dokument Specyfikacje. :)
sofs1

32

Według Java specyfikacji , nullto typ, który może być przypisany do zmiennej obiektowej (jako wartość jak zauważono w komentarzu). Nie możesz jednak tworzyć instancji ani tworzyć zmiennych tego typu, musisz użyć literału nulldostarczonego przez kompilator.


8
null to typ i wartość.
Joachim Sauer

5
nullNazwa to „przypadek” w nullrodzaju, widocznie.
strager

nullnie jest zmienną, jest literałem: JLS, 3.10.7. The Null Literal
Gerold Broser

Re " nullto typ, który można przypisać ": 1) null(w kodzie) to literał zerowy , a nie typ pusty 2) Typów nie można przypisać do zmiennych w języku Java w ogólności, patrz JLS 4.1: " Istnieją [... ] dwa rodzaje wartości danych, które mogą być przechowywane w zmiennych [...]: wartości pierwotne (§4.2) i wartości odniesienia (§4.3). " Jest to odwołanie zerowe, które można przypisać za pomocą nullliterału. ... cd ...
Gerold Broser

3) obiekt w „ zmiennej obiektowej ”, w porównaniu do zmiennej klasy, zwykle nie odnosi się do typu, ale do czasu życia. W odniesieniu do typu jest zwykle nazywana zmienną typu referencyjnego lub, w skrócie, zmienną referencyjną (typ). Zdaję sobie sprawę z 4 typów w Java API, które ujawniają zmienne instancji / obiektu (może być ich więcej): tablice z jegolength i podklasy java.awt.geom.Point2D.
Gerold Broser



12

Brak jest brakiem obiektu.


Ale typ zerowy można przypisać do każdego typu referencyjnego.
Tom Hawtin - tackline

Nie ma „typu zerowego”; null jest określoną wartością nieprymitywnych wyrażeń (tj. odwołań; w moim rozumieniu również w Javie nie ma „typu referencyjnego”).
Tommy McGuire

3
Tommy: JLS 4.1: "Istnieje również specjalny typ null, typ wyrażenia null, który nie ma nazwy."
Ken


12

JRL napisał:

Nie, nie jest, ...

Jak często, zależy to od tego, skąd na to patrzysz, w kogo bardziej wierzysz.

Według JLS tak, jest . Zwłaszcza jeśli przeformułujesz pytanie na: „Czy nulltyp jest dosłowny Object?”. Oprócz JLS 4.1 cytowanego powyżej przez Michaela Borgwardta:

Zobacz JLS 3.10.7 :

Literał null jest zawsze typu null.

i JLS 4.10 :

Podtypy typu T to wszystkie typy U takie, że T jest nadtypem U i typem zerowym.

lub JLS 4.10.2 :

Bezpośrednie typy nadrzędne typu null są wszystkimi typami odwołań innymi niż sam typ null.

[Podkreśla przeze mnie.]

Według kompilatora Eclipse 2019-09 to nie jest :

true.toString();  // Cannot invoke toString() on the primitive type boolean
null.toString();  // Cannot invoke toString() on the primitive type null

Według OpenJDKs 12.0.1 javac jest to :

true.toString();  // error: boolean cannot be dereferenced
null.toString();  // error: <null> cannot be dereferenced

Gdzie nawiasy ostre sugerują, że nulljest to inny typ niż pierwotny. I zgodnie z JLS 4.1 :

W języku programowania Java istnieją dwa rodzaje typów: typy pierwotne (...) i typy referencyjne (...).

jeśli to nie to, to jest drugie.


Claudiu napisał:

null jest trochę brzydkie.

Au contraire, nulljest piękna. Co zamiast tego sugerowałbyś jako wartość domyślną dla zmiennej typu referencyjnego? Dowolna kombinacja bitów? Witamy w naruszeniu dostępu lub, co gorsza, w piekle wskaźnikowym!


Joachim Sauer napisał:

null to typ i wartość.

W rzeczywistości istnieją trzy elementy w połączeniu z wartością null (patrz także JLS 3.10.7 ):

  1. Typ zerowy (inaczej nienazwany) .
  2. null Dosłowny .
  3. Wartość odniesienia zerowa . (Zwykle w skrócie jako wartość null lub po prostu null .)

(1) Należy zauważyć, że zgodnie z cytowanym powyżej JLS 4.10.2 typ zerowy wykorzystuje wielokrotne dziedziczenie nie tylko dla interfejsów, ale także dla klas. Co wszyscy wiemy, nie jest możliwe dla nas, programistów aplikacji.

(2) Pusty literał można sobie wyobrazić jako zmienną zdefiniowaną jako:

JVM_global final null_type null = new null_type();

Zwróć też uwagę na JLS 3.9 :

Czasami błędnie zakłada się, że za słowa kluczowe są różne sekwencje znaków:

  • nullnie jest słowem kluczowym, ale raczej literałem zerowym ( §3.10.7 ).

O null instanceof <any type>

Mając na uwadze JLS 4.10.2 („ typ null jest podtypem każdego typu”) null instanceof <any type>powinno się oceniać true, prawda? Na pierwszy rzut oka tak, ale JLS 15.20.2 daje wgląd w odpowiedź:

[...] wynikiem tego instanceofoperatora jest true, jeśli wartość w RelationalExpression nie jestnull [...]. W przeciwnym razie wynik jestfalse .

[Podkreśla przeze mnie.]

Zadaj sobie pytanie, co ma większy sens (z punktu widzenia programisty aplikacji):

  • Podanie falsei tym samym wskazanie, że wyrażenie referencyjne nie jest typem dla nas ujawnionym, tj. Wskazanie, że nie odwołuje się do niczego użytecznego dla nas

  • lub podając true, w ten sposób informując nas, że wyrażenie zwraca się do specjalnego odniesienia, odniesienia zerowego , odnoszącego się do "obiektu", nie wiemy, czy on w ogóle istnieje i który jest specjalnego typu null, który nie ma nazwy, nie jest wystawiony my, ale czy poprzez literał null podtyp jest dowolnego typu, w tym dziedziczenie wielokrotne i czy i tak ma być ignorowany? Rozważ także bardziej praktyczny przykład:

     class Car implements Vehicle {  
     ...
     Vehicle car = null;
     ...
     boolean b = car instanceof Car;  // True? There's not even an instance
     ...                              // which could be of type Car.

Co również prowadzi do:

Dlaczego instanceofnie można powiedzieć czegoś o nullprzedmiotowości we właściwy sposób ?

Nazywa się instanceofnie sameorsubtypeof. Oznacza to, że porównujemy typ instancji z typem, a nie dwoma typami. Teraz nulloznacza: „Nie ma instancji”, a jeśli nie ma instancji, nie ma typu instancji. To oczywiste, że porównywanie niczego z czymś ma prowadzić false.

Lub w „bardziej” realnym przykładzie:

  • W dłoniach mam zdjęcie jabłka ( = typ referencyjny ) z napisem »Big Apple« ( = nazwa typu odniesienia ).
  • Przede mną jest stół ( = stos ).
  • Jeśli na stole znajduje się jabłko ( = instancja ), jest do niego podłączony przewód ( = odniesienie ).
  • Trzymam w dłoni drugi koniec tego sznurka ( = zmienna referencyjna ).
  • Rysuję jabłko wzdłuż sznurka i porównuję je z moim zdjęciem ( = instanceof ).
  • Jeśli jabłko jest tej samej wielkości lub większe niż obrazek, stosuje się do niego napis »Wielkie Jabłko« ( = prawda ).
  • Jeśli jest mniejszy, to nie ( = fałsz ).
  • Jeśli na stole nie ma jabłka (= brak instancji ), a zatem nie ma sznurka ( = null ), zapis również nie ma zastosowania ( = fałsz ). Ponieważ: Czy żadne jabłko nie jest dużym jabłkiem? Nie, nie jest.


Jak podsumowuje Michael: „null jest naprawdę wyjątkowe”.


2
Jabłko i zero? Nie boisz się pozwu? :)
Gábor Lipták

9

Nie, nie jest to instancja klasy ani klasy. To odniesienie do niczego.

Edycja : nie przeczytałem specyfikacji, więc powyższe może nie być w 100% dokładne.


5

Jak wyjaśniono w rozdziale 4.1 Rodzaje typów i wartości specyfikacji języka Java, null to typ, który ma jedną wartość, odwołanie zerowe (i jest reprezentowane przez literał null):

Istnieje również specjalny typ null , typ wyrażenia null, który nie ma nazwy. Ponieważ typ null nie ma nazwy, nie można zadeklarować zmiennej typu null ani rzutować na typ null. Odwołanie o wartości null jest jedyną możliwą wartością wyrażenia typu null. Odwołanie o wartości null można zawsze rzutować na dowolny typ odwołania. W praktyce programista może zignorować typ zerowy i po prostu udawać, że nulljest to tylko specjalny literał, który może być dowolnego typu referencyjnego.

Możesz jednak przeczytać o wzorcu obiektu zerowego (którego nie polecam). Zobacz C2 Wiki lub Wikipedia, aby uzyskać więcej informacji na temat tego wzorca.



4

Nie, nie jest obiektem, ponieważ null instanceof Object zawsze zwróci false, również istnieje tylko jedna wartość null, a nie jedna dla każdej klasy.


3
W rzeczywistości też null instanceof <anytype>wróci false.
Bombe

4

Zgodnie ze specyfikacją Java ,

Istnieje również specjalny literał o wartości null, którego można użyć jako wartości dla dowolnego typu odwołania. null można przypisać do dowolnej zmiennej, z wyjątkiem zmiennych typu pierwotnego. Niewiele można zrobić z wartością zerową poza testowaniem jej obecności. Dlatego wartość null jest często używana w programach jako znacznik wskazujący, że jakiś obiekt jest niedostępny.


4

Java obsługuje obiekty za pośrednictwem odwołań. Null to podział OO-ności Javy, ponieważ spada poniżej poziomu OO. Nie, to nie jest przedmiot, to WARTOŚĆ odniesienia. I nie ma to nic wspólnego z paradygmatami obiektów, ale odnosi się do hydrauliki Javy, która umożliwia tworzenie obiektów.


3

Czy null jest wystąpieniem java.lang.Object? Nie.

Czy null jest obiektem ? zależy od definicji „ jest ”.


2
Object foo = null;
System.out.println(foo.toString()); 

Pierwsza linia pokazuje nullmoże być przypisana do typu Object, ale druga linia zademonstruje, że z pewnością nie jest Objecti ostatecznie daje w wynikujava.lang.NullPointerException


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.