Quelle est la différence entre la variable objet non initialisée et la variable objet initialisée à null en Java

12

J'ai les deux variables d'objet suivantes

Date a;
Date b=null;

Certainement, 'a' et 'b' ne font référence à aucun objet.

Maintenant, si j'invoque la déclaration suivante

System.out.println(a.toString());

Il y aura une erreur de compilation, alors que si j'invoque l'instruction suivante

System.out.println(b.toString());

Il n'y aura pas d'erreur de compilation mais il y aura une erreur d'exécution. Quelle en est la raison et quelle valeur sera réellement stockée dans «b» pour représenter une valeur nulle?

Harish_N
la source
2
a demandé et répondu plusieurs fois à SO: Pourquoi les variables locales ne sont-elles pas initialisées en Java? , Variables et membres non initialisés en Java et dans de nombreuses questions liées à ceux
gnat
@gnat, d'autres questions concernent-elles la différence entre "non initialisé" et "nul"? Ce n'est pas parce que la réponse est similaire qu'il s'agit d'une question en double.
DougM
@DougM bien sûr, avez-vous lu la première question que j'ai référée? "Y avait-il une raison pour laquelle les concepteurs de Java ont estimé que les variables locales ne devraient pas recevoir de valeur par défaut? Sérieusement, si les variables d'instance peuvent recevoir une valeur par défaut, alors pourquoi ne pouvons-nous pas faire de même pour les variables locales?" (FWIW, il ne peut pas être techniquement un doublon, simplement parce qu'il se trouve sur un autre site)
gnat
1
Cela ne résout pas la différence entre "non initialisé" et "initialisé comme nul", mais seulement "pourquoi les variables ne sont-elles pas automatiquement initialisées à null?" Même sujet, question légèrement différente.
DougM

Réponses:

3

C'est parce que l'état des variables locales est contrôlé dans sa portée

 // method/loop/if/try-catch etc...
 {
   Date d; // if it's not intialised in this scope then its not intialised  anywhere
 }

Ce qui n'est pas le cas pour les champs

class Foo{
 Date d; // it could be intialised anywhere, so its out of control and java will set to null for you
}

Maintenant, pourquoi son amende pour définir une variable à null et l'utiliser immédiatement? c'est peut-être une erreur historique qui mène parfois à des erreurs horribles

 {
  Date d = null;
  try{
  }catch{ // hide it here 
  }
  return d;
 } 

Maintenant, quelle est la différence sémantique?

Date d;

déclare simplement une variable qui peut contenir une référence qui pointe vers un objet de type Date, cependant

Date d= null; 

fait exactement la même chose mais la référence pointe cette fois sur null, null est comme n'importe quelle référence, il prend un espace d'un pointeur natif, c'est-à-dire 4 octets sur les machines 32 bits et 8 octets sur les machines 64 bits

Sleiman Jneidi
la source
cela semble simplement répéter le point soulevé et expliqué dans une réponse précédente publiée il y a une heure
gnat
@gnat Merci pour votre commentaire, mais je ne le pense pas, applaudissements
Sleiman Jneidi
Voulez-vous dire que null est également un objet stocké quelque part en mémoire et que toutes les variables d'objet affectées avec null pointent vers cet objet null.
Harish_N
@ Harish.N non, je n'ai pas dit ça, j'ai dit que c'était une référence et non un objet
Sleiman Jneidi
Dans l'exemple que vous avez donné, 'd' est une référence .. c'est une référence à un objet de type Date ... de même si null est une référence .. à quel objet il se réfère ..?
Harish_N
19

Il n'y a aucune différence pour les champs de classe. Ils sont nullpar défaut pour les objets, 0 pour les valeurs numériques et falsepour les booléens.

Pour les variables déclarées dans les méthodes - Java nécessite leur initialisation. Ne pas les initialiser provoque une erreur de temps de compilation lors de leur accès.

Quelle est la raison? Les champs de classe peuvent être modifiés par n'importe quelle méthode. Dans n'importe quel ordre, la méthode est invoquée. Tous les champs non privés peuvent être modifiés par d'autres classes et / ou classes étendant cette classe. Par conséquent, il est inutile de notifier une variable non initialisée, car elle peut être affectée à de très nombreux endroits.

Cependant, les variables à l'intérieur des méthodes sont locales et ne peuvent être modifiées qu'à l'intérieur de la méthode elle-même. Il est donc à la fois possible et rationnel de signaler d'éventuelles erreurs. Et le compilateur essaie de le faire. S'il sait que le champ n'est pas initialisé, il affichera une erreur, car ce n'est jamais ce que vous voulez. Si ce n'est pas sûr - cela donnera un avertissement, afin que vous puissiez vous en assurer.

public static class Test {
    Date a; // ok 
    Date b = null; // ok

    public void test() {
        Date c;
        Date d = null;

        System.out.println(a.toString());
        System.out.println(b.toString());
        System.out.println(c.toString()); // error
        System.out.println(d.toString()); // warning
    }
}
Dariusz
la source