Campi statici su un riferimento nullo in Java


119

statici membri ( staticcampi o staticmetodi) in Java sono associati alla rispettiva classe piuttosto che agli oggetti di questa classe. Il codice seguente tenta di accedere a un campo statico su un nullriferimento.

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

Sebbene main.getNull()ritorni null, funziona e viene visualizzato value = 10. Come funziona questo codice?



4
Per divertimento, prova Main main = null; main.getNull().value.
Marko Topolnik

1
Questo mi ricorda new Thread[]{}[-1].sleep(10);dove sleep () è un metodo statico. Questo ha avuto successo su alcune versioni precedenti di Java.
hertzsprung

Risposte:


93

Tale comportamento è specificato nelle specifiche del linguaggio Java :

un riferimento nullo può essere utilizzato per accedere a una variabile di classe (statica) senza causare un'eccezione.

Più in dettaglio, una valutazione statica del campo , come Primary.staticFieldfunziona come segue (enfasi mia) - nel tuo caso Primary = main.getNull():

  • L'espressione primaria viene valutata e il risultato viene scartato . [...]
  • Se il campo è un campo finale non vuoto, il risultato è il valore della variabile di classe specificata nella classe o nell'interfaccia che è il tipo di espressione primaria. [...]

5
Se qualcuno ha informazioni sul motivo per cui è stata fatta questa scelta, sarebbe interessante.

6
@JonofAllTrades Penso che questo sia ovvio: è ragionevole non lanciare eccezioni quando si chiama un riferimento nullo perché non importa poiché il metodo è statico.
Malcolm

13
@JonofAllTrades: la vera domanda è perché è stata fatta la scelta di consentire ai membri statici di essere chiamati come istanza ... A me sembra che porti solo confusione e codice meno leggibile.
Falanwe

2
@Falanwe: d'accordo, ed è un costrutto per il quale non ho avuto bisogno, anche se lavoro principalmente in .NET dove non è consentito. Immagino che potresti voler chiamare il metodo statico appropriato di una sottoclasse quando ti viene fornito un riferimento a una classe genitore.

8
@Falanwe Ciò è consentito, ma genera un avviso in Eclipse: "Il campo statico Main.value dovrebbe essere accessibile in modo statico". Almeno quelli di noi schizzinosi sugli avvisi (come me) eviterebbero tale codice.
Artyom

19

Perché, come hai detto, i campi statici non sono associati a un'istanza.

La capacità di accedere ai campi statici da un riferimento di istanza (come stai facendo) è semplicemente uno zucchero sintattico e non ha alcun significato aggiuntivo.
Il tuo codice viene compilato in

main.getNull(); 
Main.value

7
Lo chiamerei zucchero sintattico, più come segatura sintattica;)
Stephen Swensen,

3

Ogni volta che si accede a una variabile o metodo statico con oggetti in fase di compilazione, viene convertito in nome classe. per esempio:

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

Stamperà il valore della variabile statica perché in fase di compilazione verrà convertito in

System.out.println(Main.value);

Prova:

scarica il decompilatore e decompila il tuo file .class nel file .java e puoi vedere tutti i metodi statici o il nome dell'oggetto di riferimento variabile viene automaticamente sostituito dal nome della classe.


3
  1. L'accesso a un staticmembro con il nome della classe è legale, ma non è stato scritto che non è possibile accedere al staticmembro utilizzando la variabile di riferimento dell'oggetto. Quindi funziona qui.

  2. Una nullvariabile di riferimento oggetto può accedere a una staticvariabile di classe senza generare un'eccezione in fase di compilazione o di esecuzione.


2

La variabile statica e il metodo appartengono sempre alla classe. Quindi, ogni volta che creiamo un oggetto, solo una variabile non statica e i metodi vanno ad accumularsi insieme all'oggetto, ma lo statico risiede nell'area del metodo con la classe. Ecco perché ogni volta che proviamo ad accedere a una variabile statica oa un metodo, viene convertito in una variabile punto del nome di classe o in un nome di metodo.

Fare riferimento al collegamento sotto per maggiori dettagli.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.