Co to jest null
?
Czy null
jest na przykład coś?
Do jakiego zestawu null
należy?
Jak jest reprezentowany w pamięci?
Co to jest null
?
Czy null
jest na przykład coś?
Do jakiego zestawu null
należy?
Jak jest reprezentowany w pamięci?
Odpowiedzi:
Czy null jest czymkolwiek?
Nie, nie ma typu, który null
byłby instanceof
.
instanceof
RelationalExpression: RelationalExpression instanceof ReferenceType
W czasie wykonywania wynikiem działania
instanceof
operatora jest to,true
czy wartość RelationalExpression nie jest,null
a odwołanie może być rzutowane na ReferenceType bez podnoszenia aClassCastException
. W przeciwnym razie wynikiem jestfalse
.
Oznacza to, że dla każdego typu E
i R
dla dowolnego E o
, gdzie o == null
, o instanceof R
jest zawsze false
.
Do jakiego zestawu należy „null”?
Istnieje również specjalny typ zerowy , typ wyrażenia
null
, które nie ma nazwy. Ponieważ typ zerowy nie ma nazwy, nie można zadeklarować zmiennej typu zerowego ani rzutować na typ zerowy .null
Odniesienia jest jedyną możliwą wartość wyrazem zerowym typu.null
Odniesienia zawsze można rzucić na każdego rodzaju odniesienia. W praktyce programiści mogą zignorować typ zerowy i udawać, żenull
jest to po prostu specjalny literał, który może być dowolnego typu odniesienia.
Co to jest null?
Jak mówi powyższy cytat JLS, w praktyce możesz po prostu udawać, że to „zwykły literał, który może być dowolnego rodzaju odniesienia”.
W Javie null == null
(nie zawsze tak jest w innych językach). Należy również pamiętać, że zgodnie z umową ma również tę specjalną właściwość (z java.lang.Object
):
public boolean equals(Object obj)
Dla każdego nieprzestrzegania
null
wartości referencyjnejx
,x.equals(null)
powinienreturn false
.
Jest to również wartość domyślna (dla zmiennych, które je mają) dla wszystkich typów referencji:
- Każda zmienna klasy, zmienna instancji lub komponent tablicowy jest inicjowany z wartością domyślną podczas tworzenia:
- Dla wszystkich typów referencyjnych wartością domyślną jest
null
.
Jak to jest używane, różni się. Możesz go użyć, aby włączyć tak zwaną leniwą inicjalizację pól, w której pole miałoby swoją wartość początkową do null
momentu, aż faktycznie zostanie użyte, gdzie zostanie zastąpione wartością „rzeczywistą” (której obliczenie może być kosztowne).
Istnieją również inne zastosowania. Weźmy prawdziwy przykład z java.lang.System
:
public static Console console()
Zwraca : konsola systemowa, jeśli istnieje, w przeciwnym razie
null
.
Jest to bardzo powszechny wzorzec użycia: null
służy do oznaczenia nieistnienia obiektu.
Oto inny przykład użycia, tym razem z java.io.BufferedReader
:
public String readLine() throws IOException
Zwraca : A
String
zawierające zawartość wiersza, bez znaków zakończenia linii lubnull
jeśli osiągnięto koniec strumienia.
Tak więc tutaj readLine()
wróciłbym instanceof String
dla każdej linii, aż w końcu zwraca a, null
oznaczające koniec. Umożliwia to przetwarzanie każdej linii w następujący sposób:
String line;
while ((line = reader.readLine()) != null) {
process(line);
}
Interfejs API można zaprojektować tak, aby warunek zakończenia nie zależał od readLine()
zwrotu null
, ale widać, że ten projekt ma tę zaletę, że zwięzłość. Zauważ, że nie ma problemu z pustymi liniami, ponieważ pusta linia "" != null
.
Weźmy inny przykład, tym razem z java.util.Map<K,V>
:
V get(Object key)
Zwraca wartość, na którą jest mapowany określony klucz lub
null
jeśli ta mapa nie zawiera mapowania dla klucza.Jeśli ta mapa dopuszcza
null
wartości, wówczas zwracana wartośćnull
niekoniecznie oznacza, że mapa nie zawiera mapowania dla klucza; możliwe jest również, że mapa jawnie odwzorowuje klucznull
.containsKey
Operacja może być używany do rozróżnienia tych dwóch przypadkach.
Tutaj zaczynamy widzieć, jak używanie null
może komplikować rzeczy. Pierwsze stwierdzenie mówi, że jeśli klucz nie jest zmapowany, null
jest zwracany. Drugie stwierdzenie mówi, że nawet jeśli klucz jest zmapowany, null
można go również zwrócić.
W przeciwieństwie do tego, java.util.Hashtable
upraszcza rzeczy, nie dopuszczając null
kluczy i wartości; jego V get(Object key)
, jeśli zwraca null
, jednoznacznie oznacza, że klucz nie jest mapowany.
Możesz przeczytać resztę interfejsów API i dowiedzieć się, gdzie i jak null
jest używany. Pamiętaj, że nie zawsze są to przykłady najlepszych praktyk .
Ogólnie rzecz biorąc, null
są używane jako specjalna wartość oznaczająca:
Jak jest reprezentowany w pamięci?
W Javie? Żaden z twoich problemów. I najlepiej tak zachować.
null
to dobrze?To jest teraz subiektywne. Niektórzy twierdzą, że null
powoduje to wiele błędów programisty, których można było uniknąć. Niektórzy twierdzą, że w języku, który łapie NullPointerException
jak Java, dobrze jest go używać, ponieważ szybko zawiedziesz przy błędach programisty. Niektóre osoby unikają null
, używając wzorca obiektu zerowego itp.
Sam w sobie jest to ogromny temat, dlatego najlepiej omówić go jako odpowiedź na inne pytanie.
Kończę ten z cytatem z wynalazca null
siebie CAR Hoare (od Quicksort sławy):
Nazywam to moim błędem za miliard dolarów. To był wynalazek
null
referencji w 1965 roku. W tym czasie projektowałem pierwszy kompleksowy system typów dla referencji w języku obiektowym (ALGOL W). Moim celem było upewnienie się, że każde użycie referencji powinno być całkowicie bezpieczne, a sprawdzanie wykonywane automatycznie przez kompilator. Ale nie mogłem oprzeć się pokusie umieszczenianull
referencji, po prostu dlatego, że tak łatwo ją wdrożyć. Doprowadziło to do niezliczonych błędów, podatności i awarii systemu, które prawdopodobnie spowodowały miliard dolarów bólu i szkód w ciągu ostatnich czterdziestu lat.
Wideo z tej prezentacji sięga głębiej; to zalecany zegarek.
NIL
) w 1960 r. I prawdopodobnie wcześniej. Ale nie sądzę, żeby Hoare naprawdę starał się wymyślić wynalazek o zerowych referencjach w tym cytacie.
Czy null jest czymkolwiek?
Nie. Dlatego null instanceof X
wróci false
do wszystkich klas X
. (Nie daj się zwieść faktowi, że można przypisać null
do zmiennej, której typ jest typem obiektu. Ściśle mówiąc, przypisanie obejmuje niejawną konwersję typu; patrz poniżej.)
Do jakiego zestawu należy „null”?
Jest to jedyny element typu null, w którym typ null jest zdefiniowany w następujący sposób:
„Istnieje również specjalny typ zerowy, 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. Null referencja jest jedyną możliwą wartością wyrażenia typu null. Referencja null może być zawsze rzutowana na dowolny typ referencji. W praktyce programista może zignorować typ null i udawać, że null jest jedynie specjalnym dosłownym, który może być dowolnego typ odniesienia ”. JLS 4.1
Co to jest null?
Patrz wyżej. W niektórych kontekstach null
jest używany do oznaczenia „brak obiektu” lub „nieznany” lub „niedostępny”, ale te znaczenia są specyficzne dla aplikacji.
Jak jest reprezentowany w pamięci?
Jest to specyficzne dla implementacji i nie będzie można zobaczyć reprezentacji null
w czystym programie Java. (Ale null
jest reprezentowany jako zerowy adres / wskaźnik komputera w większości, jeśli nie we wszystkich implementacjach Java).
Co to jest null?
To nic nie znaczy.
Czy null jest czymkolwiek?
Nie, ponieważ jest niczym. To nie może być żadna instancja.
Do jakiego zestawu należy null?
Żadnego zestawu
Jak jest reprezentowany w pamięci?
Jeśli niektóre odniesienia wskazują na to:
Object o=new Object();
W pamięci sterty część miejsca przypisana do nowo utworzonego obiektu. I o wskaże na to przydzielone miejsce w pamięci.
Teraz o=null;
Oznacza to, że teraz o nie będzie wskazywać na tę przestrzeń pamięci obiektu.
Słowo kluczowe null jest literałem reprezentującym odwołanie null, które nie odwołuje się do żadnego obiektu . null jest domyślną wartością zmiennych typu referencyjnego.
Może także rzucić okiem
Null in Java (tm)
W C i C ++ „NULL” jest stałą zdefiniowaną w pliku nagłówkowym o wartości takiej jak:
0
lub:
0L
lub:
((void*)0)
w zależności od kompilatora i opcji modelu pamięci. NULL, ściśle mówiąc, nie jest częścią samego C / C ++.
W Javie (tm) „null” nie jest słowem kluczowym, lecz specjalnym literałem typu null. Może być rzutowany na dowolny typ odwołania, ale nie na dowolny typ pierwotny, taki jak int lub boolean. Literał zerowy niekoniecznie ma wartość zero. Nie można rzutować na typ zerowy ani zadeklarować zmiennej tego typu.
Reprezentacja kodu bajtowego
Java null
ma bezpośrednią obsługę JVM: do jego implementacji wykorzystywane są trzy instrukcje:
aconst_null
: np. aby ustawić zmienną na null
jak wObject o = null;
ifnull
oraz ifnonnull
: np. w celu porównania obiektu null
jak wif (o == null)
Rozdział 6 „Zestaw instrukcji wirtualnej maszyny Java” następnie wspomina o wpływie null
innych instrukcji: rzuca NullPointerException
dla wielu z nich.
2.4 „Typy referencyjne i wartości” również wspominają null
ogólnie:
Wartość referencyjna może być również specjalną referencją zerową, referencją do żadnego obiektu, która będzie tutaj oznaczona null. Odwołanie zerowe początkowo nie ma typu czasu wykonywania, ale może być rzutowane na dowolny typ. Domyślna wartość typu odwołania to null.
null
ma szczególną wartość, nie jest to przypadek niczego. Z oczywistych względów nie może to być instanceof
nic.
null
to specjalna wartość, która nie jest instancją żadnej klasy. Ilustruje to następujący program:
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);
}
}
null
nie jest to instancja String
.
void f(String o)
, miałoby to większy sens.
null w Javie jest podobny / podobny do nullptr w C ++.
Program w 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;
}
Ten sam program w Javie:
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");
}
}
}
Czy rozumiesz teraz na podstawie kodów powyżej, co jest puste w Javie? Jeśli nie, to polecam nauczyć się wskaźników w C / C ++, a wtedy zrozumiesz.
Zauważ, że w C, w przeciwieństwie do C ++, nullptr jest niezdefiniowany, ale zamiast niego używany jest NULL, który może być również używany w C ++, ale w C ++ nullptr jest bardziej preferowany niż tylko NULL, ponieważ NULL w C jest zawsze powiązany ze wskaźnikami i to jest tak, więc w C ++ przyrostek „ptr” został dołączony na końcu słowa, a także wszystkie litery są teraz małe, ale jest to mniej ważne.
W Javie każda zmienna nietypowej klasy typu jest zawsze odniesieniem do obiektu tego typu lub odziedziczonej, a null jest odwołaniem do obiektu klasy zerowej, ale nie wskaźnikiem zerowym, ponieważ w Javie nie ma czegoś takiego jak „wskaźnik”, ale odniesienia do klasy obiekty są używane zamiast tego, a null w Javie jest powiązany z odwołaniami do obiektów klasy, więc można go również nazwać „nullref” lub „nullrefobj”, ale jest on długi, więc po prostu nazwij go „null”.
W C ++ możesz używać wskaźników i wartości nullptr dla opcjonalnych elementów / zmiennych, tj. Element / zmienna, która nie ma żadnej wartości, a jeśli nie ma żadnej wartości, to jest równa nullptr, więc jak na przykład można użyć wartości null w Javie.
W Javie istnieją dwie główne kategorie typów: prymitywne i referencyjne . Zmienne zadeklarowane z wartości podstawowych w magazynie typu; zmienne zadeklarowane z odniesieniami do magazynu typu odniesienia.
String x = null;
W takim przypadku instrukcja inicjalizacji deklaruje zmienne „x”. „X” przechowuje odwołanie do ciągu. Tutaj jest zero . Po pierwsze, null nie jest prawidłową instancją obiektu, więc nie ma dla niej przydzielonej pamięci. Jest to po prostu wartość wskazująca, że odwołanie do obiektu nie odnosi się obecnie do obiektu.
Interesującym sposobem, aby zobaczyć wartość null w java jest, moim zdaniem, postrzeganie jej jako czegoś, co NIE oznacza braku informacji, ale po prostu jako dosłowną wartość, którą można przypisać do odwołania dowolnego typu. Jeśli pomyślisz o tym, jeśli oznaczało to brak informacji, to prawda, że a1 == a2 jest prawdziwa, nie ma sensu (w przypadku, gdy obaj mieli przypisaną wartość null), ponieważ mogliby naprawdę wskazywać na DOWOLNY obiekt (po prostu nie wiem na jakie obiekty powinny wskazywać) ... Nawiasem mówiąc, null == null zwraca true w Javie. Gdyby java np. Byłaby jak SQL: 1999, to null == null zwróciłoby nieznane (wartość logiczna w SQL: 1999 może przyjąć trzy wartości: prawda, fałsz i nieznana, ale w praktyce nieznana jest implementowana jako null w prawdziwych systemach) ... http://en.wikipedia.org/wiki/SQL
Krótka i precyzyjna odpowiedź, która formalnie odpowiada na wszystkie pytania z JLS:
3.10.7 Null dosłowny
Typ zerowy ma jedną wartość, odwołanie zerowe, reprezentowane przez literał zerowy zerowy, który jest utworzony ze znaków ASCII.
Literał zerowy jest zawsze typu zerowego.
Przydzielane jest tylko odwołanie typu, które jest przypisane do null. Nie przypisujesz żadnej wartości (obiektu) do odwołania. Taki przydział jest specyficzny dla JVM, ile zajmie odniesienie i w którym obszarze pamięci zostanie przydzielony.