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'appelle la déclaration 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?
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
Il n'y a aucune différence pour les champs de classe. Ils sont null
par défaut pour les objets, 0 pour les valeurs numériques et false
pour 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 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
}
}