Hay muchas respuestas excelentes que cubren los síntomas desafortunados de null, por lo que me gustaría presentar un argumento alternativo: Null es una falla en el sistema de tipos.
El propósito de un sistema de tipos es asegurar que los diferentes componentes de un programa "encajen" adecuadamente; un programa bien escrito no puede "descarrilarse" en un comportamiento indefinido.
Considere un dialecto hipotético de Java, o cualquiera que sea su lenguaje de tipo estático preferido, donde puede asignar la cadena "Hello, world!"a cualquier variable de cualquier tipo:
Foo foo1 = new Foo(); // Legal
Foo foo2 = "Hello, world!"; // Also legal
Foo foo3 = "Bonjour!"; // Not legal - only "Hello, world!" is allowed
Y puede verificar variables de esta manera:
if (foo1 != "Hello, world!") {
bar(foo1);
} else {
baz();
}
No hay nada imposible en esto: alguien podría diseñar ese lenguaje si quisiera. El valor especial no tiene que ser "Hello, world!"- que podría haber sido el número 42, la tupla (1, 4, 9), o, por ejemplo, null. ¿Pero por qué harías esto? Una variable de tipo Foosolo debe contener Foos, ¡ese es el punto principal del sistema de tipos! nullNo es Foomás de lo que "Hello, world!"es. Peor aún, nullno es un valor de ningún tipo, ¡y no hay nada que puedas hacer con él!
El programador nunca puede estar seguro de que una variable realmente contenga un Foo, y tampoco puede hacerlo el programa; Para evitar un comportamiento indefinido, debe verificar las variables "Hello, world!"antes de usarlas como Foos. Tenga en cuenta que hacer la verificación de cadena en el fragmento anterior no propaga el hecho de que foo1 es realmente un Foo- barprobablemente también tendrá su propia verificación, solo para estar seguro.
Compare eso con el uso de un Maybe/ Optiontipo con coincidencia de patrones:
case maybeFoo of
| Just foo => bar(foo)
| Nothing => baz()
Dentro de la Just foocláusula, tanto usted como el programa saben con certeza que nuestra Maybe Foovariable realmente contiene un Foovalor: que la información se propaga por la cadena de llamadas y barno necesita hacer ninguna verificación. Debido a que Maybe Fooes un tipo distinto Foo, se ve obligado a manejar la posibilidad de que pueda contener Nothing, por lo que nunca puede ser sorprendido por a NullPointerException. Puede razonar sobre su programa mucho más fácilmente y el compilador puede omitir comprobaciones nulas sabiendo que todas las variables de tipo Foorealmente contienen Foos. Todos ganan.