Champs statiques sur une référence nulle en Java

119

staticles membres ( staticchamps ou staticméthodes) en Java sont associés à leur classe respective plutôt qu'aux objets de cette classe. Le code suivant tente d'accéder à un champ statique sur une nullréférence.

public class Main
{
    private static final int value = 10;

    public Main getNull()
    {
        return null;
    }

    public static void main(String[] args)
    {
        Main main=new Main();
        System.out.println("value = "+main.getNull().value);
    }
}

Bien que main.getNull()retourne null, cela fonctionne et s'affiche value = 10. Comment fonctionne ce code?

Minuscule
la source
16
Peut-être que cette question peut vous aider à la comprendre: comment se fait-il que l'invocation d'une méthode (statique) sur une référence nulle ne lève pas NullPointerException?
Jan Gerlinger
4
Pour le plaisir, essayez Main main = null; main.getNull().value.
Marko Topolnik
1
Cela me rappelle new Thread[]{}[-1].sleep(10);où sleep () est une méthode statique. Cela réussissait sur certaines anciennes versions de Java.
hertzsprung

Réponses:

93

Ce comportement est spécifié dans la spécification du langage Java :

une référence nulle peut être utilisée pour accéder à une variable de classe (statique) sans provoquer d'exception.

Plus en détail, une évaluation de champ statique , Primary.staticFieldcomme suit (c'est moi qui souligne) - dans votre cas Primary = main.getNull(),:

  • L'expression principale est évaluée et le résultat est ignoré . [...]
  • Si le champ est un champ final non vide, le résultat est la valeur de la variable de classe spécifiée dans la classe ou l'interface qui est le type de l'expression primaire. [...]
assylies
la source
5
Si quelqu'un a des informations sur les raisons pour lesquelles ce choix a été fait, ce serait intéressant.
6
@JonofAllTrades Je pense que c'est évident: il est raisonnable de ne pas lancer d'exceptions lors de l'appel à une référence nulle car cela n'a pas d'importance puisque la méthode est statique.
Malcolm
13
@JonofAllTrades: la vraie question est de savoir pourquoi le choix de permettre aux membres statiques d'être appelés comme instance a été fait ... Pour moi, cela ne semble conduire qu'à la confusion et au code moins lisible.
Falanwe
2
@Falanwe: D'accord, et c'est une construction pour laquelle je n'ai pas eu besoin, même si je travaille principalement en .NET où ce n'est pas autorisé. Je suppose que vous voudrez peut-être appeler la méthode statique appropriée d'une sous-classe lorsque vous recevez une référence à une classe parente.
8
@Falanwe Ceci est autorisé, mais déclenche un avertissement dans Eclipse: "Le champ statique Main.value doit être accédé de manière statique". Au moins, ceux d'entre nous qui sont pointilleux sur les avertissements (comme moi) éviteraient un tel code.
Artyom
19

Parce que, comme vous l'avez dit, les champs statiques ne sont pas associés à une instance.

La possibilité d'accéder aux champs statiques à partir d'une référence d'instance (comme vous le faites) est simplement un sucre syntaxique et n'a aucune signification supplémentaire.
Votre code se compile en

main.getNull(); 
Main.value
SLaks
la source
7
J'appellerais cela du sucre syntaxique, plus comme de la sciure syntaxique;)
Stephen Swensen
3

Chaque fois que vous accédez à une variable statique ou à une méthode avec des objets au moment de la compilation, elle est convertie en nom de classe. par exemple:

Main main = null;
System.out.println(main.value);

Il affichera la valeur de la valeur de la variable statique car au moment de la compilation, il sera converti en

System.out.println(Main.value);

Preuve:

Téléchargez le décompilateur et décompilez votre fichier .class en fichier .java et vous pouvez voir toutes les méthodes statiques ou le nom d'objet référencé variable est automatiquement remplacé par le nom de classe.

Rais Alam
la source
3
  1. L'accès à un staticmembre avec le nom de classe est légal, mais son no a été écrit que l'on ne peut pas accéder au staticmembre en utilisant la variable de référence d'objet. Donc ça marche ici.

  2. Une nullvariable de référence d'objet est autorisée à accéder à une staticvariable de classe sans lever d'exception au moment de la compilation ou de l'exécution.

Kumar Vivek Mitra
la source
2

La variable statique et la méthode appartiennent toujours à la classe. Ainsi, chaque fois que nous créons un objet, seules les variables et les méthodes non statiques sont mises en tas avec l'objet, mais la statique réside dans la zone de méthode avec la classe. C'est pourquoi chaque fois que nous essayons d'accéder à une variable statique ou à une méthode, elle est convertie en nom de classe dot variable ou en nom de méthode.

Veuillez vous référer au lien ci-dessous pour plus de détails.

http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html


la source