Es gibt viele ausgezeichnete Antworten, die die unglücklichen Symptome abdecken. Daher null
möchte ich ein alternatives Argument vorlegen : Null ist ein Fehler im Typensystem.
Der Zweck eines Typensystems besteht darin, sicherzustellen, dass die verschiedenen Komponenten eines Programms richtig zusammenpassen. Ein gut geschriebenes Programm kann nicht "von der Stange kommen" undefiniertes Verhalten erkennen.
Stellen Sie sich einen hypothetischen Java-Dialekt oder eine beliebige statisch typisierte Sprache vor, in der Sie die Zeichenfolge "Hello, world!"
jeder Variablen eines beliebigen Typs zuweisen können :
Foo foo1 = new Foo(); // Legal
Foo foo2 = "Hello, world!"; // Also legal
Foo foo3 = "Bonjour!"; // Not legal - only "Hello, world!" is allowed
Und Sie können Variablen wie folgt überprüfen:
if (foo1 != "Hello, world!") {
bar(foo1);
} else {
baz();
}
Daran ist nichts unmöglich - jemand könnte eine solche Sprache entwerfen, wenn er möchte. Der spezielle Wert muss nicht sein "Hello, world!"
- es hätte die Zahl 42, das Tupel (1, 4, 9)
oder sagen wir, sein können null
. Aber warum würdest du das tun? Eine Variable vom Typ Foo
sollte nur Foo
s enthalten - das ist der springende Punkt des Typsystems! null
ist nicht Foo
mehr als es "Hello, world!"
ist. Schlimmer noch, es null
gibt keinen Wert irgendeiner Art und Sie können nichts damit anfangen!
Der Programmierer kann niemals sicher sein, dass eine Variable tatsächlich a enthält Foo
, und das Programm kann es auch nicht. Um ein undefiniertes Verhalten zu vermeiden, müssen die Variablen überprüft werden, "Hello, world!"
bevor sie als Foo
s verwendet werden. Beachten Sie, dass das Ausführen der Zeichenfolgenprüfung im vorherigen Snippet nicht die Tatsache verbreitet, dass foo1 wirklich ein Foo
- bar
wahrscheinlich auch eine eigene Prüfung hat, nur um sicherzugehen.
Vergleichen Sie dies mit der Verwendung eines Maybe
/ Option
-Typs mit Mustererkennung:
case maybeFoo of
| Just foo => bar(foo)
| Nothing => baz()
Innerhalb der Just foo
Klausel wissen sowohl Sie als auch das Programm, dass unsere Maybe Foo
Variable wirklich einen Foo
Wert enthält - diese Informationen werden in der Aufrufkette weitergegeben und bar
müssen nicht überprüft werden. Da Maybe Foo
es sich um einen anderen Typ handelt Foo
, sind Sie gezwungen, mit der Möglichkeit Nothing
umzugehen , die er enthalten könnte NullPointerException
. Sie können viel einfacher über Ihr Programm nachdenken, und der Compiler kann Nullprüfungen auslassen, wenn er weiß, dass alle Variablen des Typs Foo
tatsächlich Foo
s enthalten . Jeder gewinnt.