Qu'est-ce qui est nul en Java?

252

Qu'est-ce que c'est null?

Est-ce nullune instance de quelque chose?

À quel ensemble nullappartient-il?

Comment est-il représenté dans la mémoire?

unj2
la source
yegor256. À propos de null de JLS. "Le littéral nul. Le type nul a une valeur, la référence nulle, représentée par le littéral nul null, qui est formé de caractères ASCII. Un littéral nul est toujours de type nul." À propos des points de l'article. «Objets mutables et incomplets» est une fonctionnalité. «Slow Failing» est une capacité de par sa conception. «Pensée informatique vs pensée objet» ne sont que deux façons de penser. La «sémantique ambiguë» est trop subjective. La «gestion des erreurs ad hoc» est un autre type de traitement des erreurs. Null est un littéral ou tout autre élément spécifié dans JLS au lieu d'être bon ou mauvais.
Oleksii Kyslytsyn

Réponses:

310

Null est-il une instance de quoi que ce soit?

Non, il n'y a pas de type qui nullsoit un instanceof.

15.20.2 Opérateur de comparaison de types instanceof

RelationalExpression:
    RelationalExpression instanceof ReferenceType

Au moment de l'exécution, le résultat de l' instanceofopérateur est truesi la valeur de RelationalExpression ne l'est pas nullet que la référence peut être convertie en ReferenceType sans augmenter a ClassCastException. Sinon, le résultat est false.

Cela signifie que pour tout type Eet R, pour tout E o, où o == null, o instanceof Rest toujours false.


À quel ensemble appartient «null»?

JLS 4.1 Les types de types et de valeurs

Il existe également un type null spécial , le type de l'expression null, qui n'a pas de nom. Étant donné que le type nul n'a pas de nom, il est impossible de déclarer une variable du type nul ou de transtyper en type nul . La nullréférence est la seule valeur possible d'une expression de type null . La nullréférence peut toujours être convertie en n'importe quel type de référence. En pratique, le programmeur peut ignorer le type nul et prétendre qu'il nulls'agit simplement d'un littéral spécial qui peut être de n'importe quel type de référence.


Qu'est-ce qui est nul?

Comme le dit la citation de JLS ci-dessus, dans la pratique, vous pouvez simplement prétendre que c'est "simplement un littéral spécial qui peut être de n'importe quel type de référence".

En Java, null == null(ce n'est pas toujours le cas dans d'autres langues). Notez également que par contrat, il possède également cette propriété spéciale (de java.lang.Object):

public boolean equals(Object obj)

Pour toute nullvaleur non référence x, x.equals(null)devrait return false.

Il s'agit également de la valeur par défaut (pour les variables qui en disposent) pour tous les types de référence:

JLS 4.12.5 Valeurs initiales des variables

  • Chaque variable de classe, variable d'instance ou composant de tableau est initialisé avec une valeur par défaut lors de sa création:
    • Pour tous les types de référence, la valeur par défaut est null.

La façon dont cela est utilisé varie. Vous pouvez l'utiliser pour activer ce qu'on appelle l' initialisation différée des champs, où un champ aurait sa valeur initiale nulljusqu'à ce qu'il soit réellement utilisé, où il est remplacé par la valeur "réelle" (qui peut être coûteuse à calculer).

Il existe également d'autres utilisations. Prenons un exemple réel de java.lang.System:

public static Console console()

Renvoie : la console système, le cas échéant, sinon null.

Il s'agit d'un modèle d'utilisation très courant: nullest utilisé pour indiquer la non-existence d'un objet.

Voici un autre exemple d'utilisation, cette fois de java.io.BufferedReader:

public String readLine() throws IOException

Renvoie : A Stringcontenant le contenu de la ligne, sans inclure les caractères de terminaison de ligne, ou nullsi la fin du flux a été atteinte.

Donc ici, readLine()reviendrait instanceof Stringpour chaque ligne, jusqu'à ce qu'elle retourne finalement un nullpour signifier la fin. Cela vous permet de traiter chaque ligne comme suit:

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

On peut concevoir l'API pour que la condition de terminaison ne dépende pas du readLine()retour null, mais on peut voir que cette conception a l'avantage de rendre les choses concises. Notez qu'il n'y a pas de problème avec les lignes vides, car une ligne vide "" != null.

Prenons un autre exemple, cette fois de java.util.Map<K,V>:

V get(Object key)

Renvoie la valeur à laquelle la clé spécifiée est mappée, ou nullsi cette mappe ne contient aucun mappage pour la clé.

Si cette mappe autorise des nullvaleurs, une valeur de retour de nulln'indique pas nécessairement que la mappe ne contient pas de mappage pour la clé; il est également possible que la carte mappe explicitement la clé null. L' containsKeyopération peut être utilisée pour distinguer ces deux cas.

Ici, nous commençons à voir comment l'utilisation nullpeut compliquer les choses. La première instruction indique que si la clé n'est pas mappée, elle nullest renvoyée. La deuxième déclaration indique que même si la clé est mappée, elle nullpeut également être renvoyée.

En revanche, java.util.Hashtablesimplifie les choses en n'autorisant pas les nullclés et les valeurs; son V get(Object key), s'il revient null, signifie sans ambiguïté que la clé n'est pas mappée.

Vous pouvez lire le reste des API et trouver où et comment nullest utilisé. Gardez à l'esprit qu'ils ne sont pas toujours des exemples de bonnes pratiques .

D'une manière générale, nullsont utilisés comme valeur spéciale pour signifier:

  • État non initialisé
  • Condition de résiliation
  • Objet inexistant
  • Une valeur inconnue

Comment est-il représenté dans la mémoire?

En Java? Aucun de vos soucis. Et c'est mieux gardé de cette façon.


C'est nullune bonne chose?

C'est maintenant subjectivement limite. Certaines personnes disent que cela nullprovoque de nombreuses erreurs de programmation qui auraient pu être évitées. Certains disent que dans un langage qui attrape NullPointerExceptioncomme Java, il est bon de l'utiliser car vous échouerez rapidement sur les erreurs de programmation. Certaines personnes évitent nulld'utiliser le modèle d'objet nul , etc.

Il s'agit d'un énorme sujet en soi, il est donc préférable de le discuter comme réponse à une autre question.

Je terminerai ceci par une citation de l'inventeur de nulllui-même, CAR Hoare (de renommée quicksort):

J'appelle cela mon erreur d'un milliard de dollars. C'était l'invention de la nullréférence en 1965. A cette époque, je concevais le premier système de type complet pour les références dans un langage orienté objet (ALGOL W). Mon objectif était de garantir que toute utilisation des références soit absolument sûre, la vérification étant effectuée automatiquement par le compilateur. Mais je n'ai pas pu résister à la tentation de mettre une nullréférence, tout simplement parce qu'elle était si simple à mettre en œuvre. Cela a conduit à d'innombrables erreurs, vulnérabilités et plantages du système, qui ont probablement causé un milliard de dollars de douleur et de dommages au cours des quarante dernières années.

La vidéo de cette présentation va plus loin; c'est une montre recommandée.

polygénelubrifiants
la source
5
Des références nulles existaient dans LISP (as NIL) en 1960, et probablement plus tôt. Mais je ne pense pas que Hoare essaie vraiment de revendiquer l'invention de références nulles dans cette citation.
Stephen C
7
Hoare n'essaie pas de revendiquer l'invention de références nulles; il prétend simplement les avoir mis à disposition dans un lieu particulièrement influent. Il existe de nombreux langages, y compris Java, qui s'inspirent clairement d'Algol, et si leur utilisation de références nulles était même en partie inspirée ou copiée d'Algol, Hoare a raison d'assumer une partie du blâme pour le coût de ceux-ci. Je pense cependant que son estimation est plutôt faible. Un billion de dollars pourrait être plus proche du véritable coût.
cjs
32

Null est-il une instance de quoi que ce soit?

C'est pourquoi null instanceof Xreviendra falsepour toutes les classes X. (Ne vous laissez pas berner par le fait que vous pouvez affecter nullà une variable dont le type est un type d'objet. À proprement parler, l'affectation implique une conversion de type implicite; voir ci-dessous.)

À quel ensemble appartient «null»?

Il s'agit du seul et unique membre du type null, où le type null est défini comme suit:

"Il existe également un type null spécial, le type de l'expression null, qui n'a pas de nom. Comme le type null n'a pas de nom, il est impossible de déclarer une variable de type null ou de transtyper en type null. Le null référence est la seule valeur possible d'une expression de type null. La référence null peut toujours être convertie en n'importe quel type de référence. En pratique, le programmeur peut ignorer le type null et prétendre simplement que null est simplement un littéral spécial qui peut être de n'importe quel type. Type de référence." JLS 4.1

Qu'est-ce qui est nul?

Voir au dessus. Dans certains contextes, nullest utilisé pour désigner "aucun objet" ou "inconnu" ou "indisponible", mais ces significations sont spécifiques à l'application.

Comment est-il représenté dans la mémoire?

C'est spécifique à l'implémentation, et vous ne pourrez pas voir la représentation de nulldans un programme Java pur. (Mais nullest représenté comme une adresse / pointeur de machine zéro dans la plupart, sinon toutes les implémentations Java.)

Stephen C
la source
14

Qu'est-ce qui est nul?

Ce n'est rien.

Null est-il une instance de quoi que ce soit?

Non car ce n'est rien. Cela ne peut pas être l'instance de quelque chose.

À quel ensemble appartient null?

Aucun ensemble

Comment est-il représenté dans la mémoire?

Si certaines références le désignent comme:

Object o=new Object();

Dans la mémoire de tas, un espace est attribué au nouvel objet créé. Et o pointera vers cet espace attribué en mémoire.

Maintenant o=null;

Cela signifie maintenant que o ne pointera pas vers cet espace mémoire de l'objet.

Sanjay Jain
la source
1
"Now o = null; Cela signifie que maintenant o ne pointera pas vers cet espace mémoire de l'objet." Je pense que c'est ainsi que fonctionne Garbage Collection en JAVA
Hardik Mishra
9

Non, ce n'est pas l'instance de quoi que ce soit, instanceof sera toujours faux.

À M
la source
7

Le mot clé null est un littéral qui représente une référence nulle, une référence qui ne fait référence à aucun objet . null est la valeur par défaut des variables de type référence.

Peut-être aussi jeter un oeil à

null: Glossaire Java

Adriaan Stander
la source
2
Ce n'est pas un mot-clé, c'est un littéral . Citation de mauvaise qualité et non normative.
Marquis de Lorne
6

Null n'est une instance d'aucune classe.

Cependant, vous pouvez affecter null aux variables de tout type (objet ou tableau):

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

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

Null en Java (tm)

En C et C ++, "NULL" est une constante définie dans un fichier d'en-tête, avec une valeur comme:

    0

ou:

    0L

ou:

    ((void*)0)

selon les options du compilateur et du modèle de mémoire. NULL ne fait pas à proprement parler partie de C / C ++ lui-même.

En Java (tm), "null" n'est pas un mot-clé, mais un littéral spécial de type null. Il peut être converti en n'importe quel type de référence, mais pas en n'importe quel type primitif tel que int ou booléen. Le littéral nul n'a pas nécessairement la valeur zéro. Et il est impossible de transtyper en type null ou de déclarer une variable de ce type.

p27
la source
5

Représentation du bytecode

Java nulla un support JVM direct: trois instructions sont utilisées pour l'implémenter:

  • aconst_null: par exemple, pour définir une variable nullcomme dansObject o = null;
  • ifnullet ifnonnull: par exemple pour comparer un objet nullcomme dansif (o == null)

Le chapitre 6 "Le jeu d'instructions de la machine virtuelle Java" mentionne ensuite les effets de nullsur d'autres instructions: il en lance un NullPointerExceptionpour beaucoup d'entre elles.

2.4. "Types et valeurs de référence" mentionne également nullen termes génériques:

Une valeur de référence peut également être la référence null spéciale, une référence à aucun objet, qui sera désignée ici par null. La référence null n'a initialement aucun type d'exécution, mais peut être convertie en n'importe quel type. La valeur par défaut d'un type de référence est null.

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

nullest une valeur spéciale, ce n'est pas une instance de quoi que ce soit. Pour une raison évidente, cela ne peut être instanceofrien.

fastcodejava
la source
3

nullest une valeur spéciale qui n'est une instance d'aucune classe. Ceci est illustré par le programme suivant:

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
la source
6
La seule chose que cet exemple montre est que ce nulln'est pas une instance de String.
Sasha Chedygov
4
Si vous changez la signature en void f(String o), cela aurait plus de sens.
Thilo
2

null en Java est similaire à nullptr en C ++.

Programme 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;
}

Même programme 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");
        }
    }
}

Comprenez-vous maintenant des codes ci-dessus ce qui est nul en Java? Si non, je vous recommande d'apprendre les pointeurs en C / C ++ et vous comprendrez.

Notez qu'en C, contrairement à C ++, nullptr n'est pas défini, mais NULL est utilisé à la place, ce qui peut également être utilisé en C ++, mais en C ++ nullptr est plus préférable que NULL, car le NULL en C est toujours lié aux pointeurs et c'est il, donc en C ++ le suffixe "ptr" a été ajouté à la fin du mot, et aussi toutes les lettres sont maintenant en minuscules, mais c'est moins important.

En Java, chaque variable de classe de type non primitive est toujours une référence à un objet de ce type ou héritée et null est une référence d'objet de classe null, mais pas un pointeur null, car en Java, il n'y a pas de "pointeur", mais des références à la classe les objets sont utilisés à la place, et null en Java est lié aux références aux objets de classe, vous pouvez donc aussi l'appeler "nullref" ou "nullrefobj", mais c'est long, alors appelez-le simplement "null".

En C ++, vous pouvez utiliser des pointeurs et la valeur nullptr pour les membres / variables facultatifs , c'est-à-dire le membre / variable qui n'a pas de valeur et s'il n'a pas de valeur, il est égal à nullptr, alors comment null en Java peut être utilisé par exemple.


la source
1

Il existe deux grandes catégories de types en Java: primitive et référence . Variables déclarées d'un magasin de type primitif; les variables déclarées d'un type de référence stockent les références.

String x = null;

Dans ce cas, l'instruction d'initialisation déclare une variable «x». «X» stocke la référence de chaîne. C'est nul ici. Tout d'abord, null n'est pas une instance d'objet valide, il n'y a donc pas de mémoire allouée pour cela. Il s'agit simplement d'une valeur qui indique que la référence d'objet ne fait pas actuellement référence à un objet.

Anand
la source
0

Une façon intéressante de voir null en java à mon avis est de le voir comme quelque chose qui NE dénote PAS une absence d'information mais simplement comme une valeur littérale qui peut être assignée à une référence de n'importe quel type. Si vous y pensez si cela dénotait une absence d'information, alors pour a1 == a2 être vrai n'a pas de sens (au cas où on leur attribuerait une valeur nulle) car ils pourraient vraiment pointer vers N'IMPORTE QUEL objet (nous avons simplement Je ne sais pas sur quels objets ils devraient pointer) ... Au fait, null == null renvoie true en java. Si java, par exemple, serait comme SQL: 1999, alors null == null retournerait inconnu (une valeur booléenne dans SQL: 1999 peut prendre trois valeurs: true, false et unknown mais en pratique unknown est implémenté comme null dans les systèmes réels) ... http://en.wikipedia.org/wiki/SQL

Bat0u89
la source
0

Réponse courte et précise qui répond formellement à toutes vos questions de JLS:

3.10.7. The Null Literal

Le type null a une valeur, la référence null, représentée par le null littéral null, qui est formé de caractères ASCII.

Un littéral nul est toujours de type nul.

Seule une référence de type affectée à null est allouée. Vous n'affectez aucune valeur (objet) à la référence. Cette allocation est spécifique à la machine virtuelle Java combien de référence prendra et dans quelle zone mémoire elle sera allouée.

Oleksii Kyslytsyn
la source