¿Qué es nulo en Java?

252

¿Qué es null?

¿Es nulluna instancia de algo?

¿A qué conjunto nullpertenece?

¿Cómo se representa en la memoria?

unj2
fuente
yegor256. Sobre nulo de JLS. "El literal nulo. El tipo nulo tiene un valor, la referencia nula, representada por el nulo literal nulo, que se forma a partir de caracteres ASCII. Un literal nulo siempre es del tipo nulo". Sobre puntos en el artículo. 'Objetos mutables e incompletos' es una característica. 'Slow Failing' es una habilidad por diseño. El "pensamiento informático frente al pensamiento de objetos" son solo dos formas de pensar. 'Semántica ambigua' es demasiado subjetiva. El 'Manejo de errores ad-hoc' es otro tipo de trabajo con errores. Nulo es un literal o cualquier otra cosa especificada en JLS en contraste con no ser bueno o malo.
Oleksii Kyslytsyn

Respuestas:

310

¿Es nulo una instancia de algo?

No, no hay ningún tipo que nullsea ​​un instanceof.

15.20.2 Operador de comparación de tipos instanceof

RelationalExpression:
    RelationalExpression instanceof ReferenceType

En tiempo de ejecución, el resultado del instanceofoperador es truesi el valor de RelationalExpression no es nully la referencia podría convertirse al ReferenceType sin generar a ClassCastException. De lo contrario, el resultado es false.

Esto significa que para cualquier tipo Ey R, para cualquier E o, donde o == null, o instanceof Rsiempre es false.


¿A qué conjunto pertenece 'nulo'?

JLS 4.1 Las clases de tipos y valores

También hay un tipo nulo especial , el tipo de expresión null, que no tiene nombre. Como el tipo nulo no tiene nombre, es imposible declarar una variable del tipo nulo o convertir al tipo nulo . La nullreferencia es el único valor posible de una expresión de tipo nulo . La nullreferencia siempre se puede convertir a cualquier tipo de referencia. En la práctica, el programador puede ignorar el tipo nulo y simplemente pretender que nulles simplemente un literal especial que puede ser de cualquier tipo de referencia.


¿Qué es nulo?

Como dice la cita de JLS anterior, en la práctica simplemente puede pretender que es "simplemente un literal especial que puede ser de cualquier tipo de referencia".

En Java, null == null(este no es siempre el caso en otros idiomas). Tenga en cuenta también que, por contrato, también tiene esta propiedad especial (de java.lang.Object):

public boolean equals(Object obj)

Para cualquier nullvalor que no sea de referencia x, x.equals(null)debería return false.

También es el valor predeterminado (para las variables que los tienen) para todos los tipos de referencia:

JLS 4.12.5 Valores iniciales de variables

  • Cada variable de clase, variable de instancia o componente de matriz se inicializa con un valor predeterminado cuando se crea:
    • Para todos los tipos de referencia, el valor predeterminado es null.

Cómo se usa esto varía. Puede usarlo para habilitar lo que se llama inicialización diferida de campos, donde un campo tendría su valor inicial de nullhasta que realmente se usara, donde sea reemplazado por el valor "real" (que puede ser costoso de calcular).

También hay otros usos. Tomemos un ejemplo real de java.lang.System:

public static Console console()

Devoluciones : la consola del sistema, si existe, de lo contrario null.

Este es un patrón de uso muy común: nullse usa para denotar la inexistencia de un objeto.

Aquí hay otro ejemplo de uso, esta vez de java.io.BufferedReader:

public String readLine() throws IOException

Devuelve : A que Stringcontiene el contenido de la línea, sin incluir ningún carácter de terminación de línea, o nullsi se ha alcanzado el final de la secuencia.

Entonces, aquí, readLine()volvería instanceof Stringpara cada línea, hasta que finalmente devuelva un nullpara significar el final. Esto le permite procesar cada línea de la siguiente manera:

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

Se puede diseñar la API para que la condición de terminación no dependa de la readLine()devolución null, pero se puede ver que este diseño tiene el beneficio de hacer que las cosas sean concisas. Tenga en cuenta que no hay problema con las líneas vacías, porque hay una línea vacía "" != null.

Tomemos otro ejemplo, esta vez de java.util.Map<K,V>:

V get(Object key)

Devuelve el valor al que se asigna la clave especificada, o nullsi este mapa no contiene ninguna asignación para la clave.

Si este mapa permite nullvalores, entonces un valor de retorno de nullno necesariamente indica que el mapa no contiene asignación para la clave; También es posible que el mapa asigne explícitamente la clave null. La containsKeyoperación puede usarse para distinguir estos dos casos.

Aquí comenzamos a ver cómo usar nullpuede complicar las cosas. La primera declaración dice que si la clave no está asignada, nullse devuelve. La segunda declaración dice que incluso si se asigna la clave, nullpuede también ser devuelto.

Por el contrario, java.util.Hashtablesimplifica las cosas al no permitir nullclaves y valores; su V get(Object key), si los rendimientos null, sin ambigüedad significa que la clave no está asignada.

Puede leer el resto de las API y encontrar dónde y cómo nullse usa. Tenga en cuenta que no siempre son los mejores ejemplos de práctica .

En términos generales, nullse utilizan como un valor especial para significar:

  • Estado no inicializado
  • Condición de terminación
  • Objeto no existente
  • Un valor desconocido

¿Cómo se representa en la memoria?

En Java Nada de tu incumbencia. Y es mejor mantenerlo así.


Es nullalgo bueno

Esto ahora es límite subjetivo. Algunas personas dicen que eso nullcausa muchos errores de programador que podrían haberse evitado. Algunos dicen que en un lenguaje que atrapa NullPointerExceptioncomo Java, es bueno usarlo porque fallará rápidamente en los errores del programador. Algunas personas evitan nullmediante el uso de patrones de objetos nulos , etc.

Este es un tema enorme en sí mismo, por lo que es mejor discutirlo como respuesta a otra pregunta.

Terminaré esto con una cita del inventor de nullsí mismo, CAR Hoare (de fama rápida):

Lo llamo mi error de mil millones de dólares. Fue la invención de la nullreferencia en 1965. En ese momento, estaba diseñando el primer sistema de tipos completo para referencias en un lenguaje orientado a objetos (ALGOL W). Mi objetivo era asegurar que todo uso de referencias debería ser absolutamente seguro, con una verificación realizada automáticamente por el compilador. Pero no pude resistir la tentación de poner una nullreferencia, simplemente porque era muy fácil de implementar. Esto ha llevado a innumerables errores, vulnerabilidades y fallas en el sistema, lo que probablemente ha causado miles de millones de dólares de dolor y daños en los últimos cuarenta años.

El video de esta presentación es más profundo; Es un reloj recomendado.

poligenelubricantes
fuente
55
Las referencias nulas existieron en LISP (as NIL) en 1960, y probablemente antes. Pero no creo que Hoare realmente esté tratando de reclamar la invención de referencias nulas en esa cita.
Stephen C
77
Hoare no está tratando de reclamar la invención de referencias nulas; él simplemente afirma que los hizo disponibles en un lugar particularmente influyente. Hay muchos lenguajes, incluido Java, que claramente se inspiraron en Algol, y si su uso de referencias nulas fue en parte inspirado o copiado de Algol, Hoare tiene razón al asumir parte de la culpa por el costo de estos. Sin embargo, siento que su estimación es bastante baja. Un billón de dólares podría estar más cerca del costo real.
cjs
32

¿Es nulo una instancia de algo?

No. Por eso null instanceof Xregresará falsepara todas las clases X. (No se deje engañar por el hecho de que puede asignar nulla una variable cuyo tipo es un tipo de objeto. Estrictamente hablando, la asignación implica una conversión de tipo implícita; ver más abajo).

¿A qué conjunto pertenece 'nulo'?

Es el único miembro del tipo nulo, donde el tipo nulo se define de la siguiente manera:

"También hay un tipo nulo especial, el tipo de la expresión nulo, que no tiene nombre. Debido a que el tipo nulo no tiene nombre, es imposible declarar una variable del tipo nulo o emitir al tipo nulo. El nulo referencia es el único valor posible de una expresión de tipo nulo. La referencia nula siempre se puede convertir a cualquier tipo de referencia. En la práctica, el programador puede ignorar el tipo nulo y simplemente pretender que nulo es simplemente un literal especial que puede ser de cualquier tipo tipo de referencia." JLS 4.1

¿Qué es nulo?

Véase más arriba. En algunos contextos, nullse usa para denotar "sin objeto" o "desconocido" o "no disponible", pero estos significados son específicos de la aplicación.

¿Cómo se representa en la memoria?

Eso es específico de la implementación, y no podrá ver la representación de nullun programa Java puro. (Pero nullse representa como una dirección / puntero de máquina cero en la mayoría, si no en todas las implementaciones de Java).

Stephen C
fuente
14

¿Qué es nulo?

No es nada.

¿Es nulo una instancia de algo?

No, ya que no es nada. No puede ser una instancia de nada.

¿A qué conjunto pertenece nulo?

No hay ningún conjunto

¿Cómo se representa en la memoria?

Si algunos puntos de referencia son:

Object o=new Object();

En la memoria del montón, se asigna algo de espacio al nuevo objeto creado. Y o apuntará a ese espacio asignado en la memoria.

Ahora o=null;

Esto significa que ahora o no apuntará a ese espacio de memoria del objeto.

Sanjay Jain
fuente
1
"Ahora o = nulo; Esto significa que ahora o no apuntará a ese espacio de memoria del objeto". Creo que así es como funciona la recolección de basura en JAVA
Hardik Mishra
9

No, no es la instancia de nada, la instancia de siempre será falsa.

Tom
fuente
7

La palabra clave nula es un literal que representa una referencia nula, una que no hace referencia a ningún objeto . nulo es el valor predeterminado de las variables de tipo de referencia.

También quizás eche un vistazo a

nulo: glosario de Java

Adriaan Stander
fuente
2
No es una palabra clave, es un literal . Mala calidad y citas no normativas.
Marqués de Lorne
6

Nulo no es una instancia de ninguna clase.

Sin embargo, puede asignar nulo a variables de cualquier tipo (objeto o matriz):

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

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

Nulo en Java (tm)

En C y C ++, "NULL" es una constante definida en un archivo de encabezado, con un valor como:

    0

o:

    0L

o:

    ((void*)0)

dependiendo del compilador y las opciones del modelo de memoria. NULL no es, estrictamente hablando, parte de C / C ++ en sí.

En Java (tm), "nulo" no es una palabra clave, sino un literal especial del tipo nulo. Se puede convertir a cualquier tipo de referencia, pero no a ningún tipo primitivo como int o boolean. El literal nulo no necesariamente tiene valor cero. Y es imposible convertir al tipo nulo o declarar una variable de este tipo.

p27
fuente
5

Representación de bytecode

Java nulltiene soporte directo de JVM: se utilizan tres instrucciones para implementarlo:

  • aconst_null: por ejemplo, para establecer una variable nullcomo enObject o = null;
  • ifnully ifnonnull: por ejemplo, para comparar un objeto nullcomo enif (o == null)

El Capítulo 6 "El conjunto de instrucciones de la máquina virtual Java" luego menciona los efectos de nullotras instrucciones: arroja unNullPointerException para muchos de ellos.

2.4. "Tipos y valores de referencia" también menciona nullen términos genéricos:

Un valor de referencia también puede ser la referencia nula especial, una referencia a ningún objeto, que se indicará aquí por nulo. La referencia nula inicialmente no tiene ningún tipo de tiempo de ejecución, pero se puede convertir a cualquier tipo. El valor predeterminado de un tipo de referencia es nulo.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
4

nulles un valor especial, no es instancia de nada. Obviamente, no puede ser instanceofnada.

fastcodejava
fuente
3

nulles un valor especial que no es una instancia de ninguna clase. Esto se ilustra con el siguiente programa:

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);
   }
}
Itay Maman
fuente
66
Lo único que muestra el ejemplo es que nullno es una instancia de String.
Sasha Chedygov
44
Si cambiara la firma a void f(String o), tendría más sentido.
Thilo
2

null en Java es como / similar a nullptr en C ++.

Programa en 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;
}

Mismo programa en Java:

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");
        }
    }
}

¿Entiendes ahora de los códigos anteriores qué es nulo en Java? Si no es así, le recomiendo que aprenda punteros en C / C ++ y luego lo comprenderá.

Tenga en cuenta que en C, a diferencia de C ++, nullptr no está definido, pero se usa NULL, que también se puede usar en C ++, pero en C ++ nullptr es más preferible que solo NULL, porque NULL en C siempre está relacionado con punteros y eso es así que, en C ++, el sufijo "ptr" se agregó al final de la palabra, y también todas las letras ahora están en minúsculas, pero esto es menos importante.

En Java, cada variable de tipo de clase no primitiva es siempre referencia a un objeto de ese tipo o heredado y nulo es referencia de objeto de clase nula, pero no puntero nulo, porque en Java no existe tal "puntero", sino referencias a clase en su lugar, se utilizan objetos, y nulo en Java está relacionado con referencias de objetos de clase, por lo que también puede llamarlo como "nullref" o "nullrefobj", pero esto es largo, así que llámelo "nulo".

En C ++ puede usar punteros y el valor nullptr para miembros / variables opcionales , es decir, miembro / variable que no tiene valor y si no tiene valor, entonces es igual a nullptr, entonces, ¿cómo puede usarse nulo en Java, por ejemplo?


fuente
1

Hay dos categorías principales de tipos en Java: primitivo y de referencia . Las variables declaradas de un tipo primitivo almacenan valores; Las variables declaradas de un tipo de referencia almacenan referencias.

String x = null;

En este caso, la declaración de inicialización declara una variable "x". "X" almacena la referencia de cadena. Es nulo aquí. En primer lugar, nulo no es una instancia de objeto válida, por lo que no hay memoria asignada para ello. Es simplemente un valor que indica que la referencia del objeto no se refiere actualmente a un objeto.

Anand
fuente
0

Una forma interesante de ver nulo en Java en mi opinión es verlo como algo que NO denota la ausencia de información, sino simplemente como un valor literal que se puede asignar a una referencia de cualquier tipo. Si lo piensa si denota la ausencia de información, entonces a1 == a2 es verdadero no tiene sentido (en caso de que a ambos se les haya asignado un valor nulo) ya que realmente podrían estar apuntando a CUALQUIER objeto (simplemente no sé a qué objetos deberían apuntar) ... Por cierto, null == null devuelve verdadero en java. Si Java, por ejemplo, fuera como SQL: 1999, entonces nulo == nulo devolvería desconocido (un valor booleano en SQL: 1999 puede tomar tres valores: verdadero, falso y desconocido, pero en la práctica desconocido se implementa como nulo en sistemas reales) ... http://en.wikipedia.org/wiki/SQL

Bat0u89
fuente
0

Respuesta corta y precisa que responde a todas sus preguntas formalmente de JLS:

3.10.7. El literal nulo

El tipo nulo tiene un valor, la referencia nula, representada por el nulo literal nulo, que se forma a partir de caracteres ASCII.

Un literal nulo siempre es del tipo nulo.

Solo se asigna una referencia de tipo que se asigna a nulo. No asigna ningún valor (objeto) a la referencia. Dicha asignación es específica para JVM cuánta referencia tomará y en qué área de memoria se asignará.

Oleksii Kyslytsyn
fuente