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?



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. [...]

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

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.


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.


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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.