Statische Felder in einer Nullreferenz in Java


119

staticMitglieder ( staticFelder oder staticMethoden) in Java sind eher ihrer jeweiligen Klasse als den Objekten dieser Klasse zugeordnet. Der folgende Code versucht, auf ein statisches Feld in einer nullReferenz zuzugreifen .

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

Obwohl main.getNull()zurückgegeben null, funktioniert es und wird angezeigt value = 10. Wie funktioniert dieser Code?



4
Versuchen Sie es zum Spaß Main main = null; main.getNull().value.
Marko Topolnik

1
Dies erinnert mich daran, new Thread[]{}[-1].sleep(10);wo sleep () eine statische Methode ist. Dies war früher bei einigen älteren Java-Versionen erfolgreich.
Hertzsprung

Antworten:


93

Dieses Verhalten ist in der Java-Sprachspezifikation angegeben :

Eine Nullreferenz kann verwendet werden, um auf eine (statische) Klassenvariable zuzugreifen, ohne eine Ausnahme zu verursachen.

Im Einzelnen funktioniert eine statische Feldauswertung wie Primary.staticFieldfolgt (Hervorhebung von mir) - in Ihrem Fall Primary = main.getNull():

  • Der primäre Ausdruck wird ausgewertet und das Ergebnis verworfen . [...]
  • Wenn das Feld ein nicht leeres Endfeld ist, ist das Ergebnis der Wert der angegebenen Klassenvariablen in der Klasse oder Schnittstelle, die der Typ des primären Ausdrucks ist. [...]

5
Wenn jemand Informationen darüber hat, warum diese Wahl getroffen wurde, wäre das interessant.

6
@ JonofAllTrades Ich denke, das ist offensichtlich: Es ist vernünftig, beim Aufrufen einer Nullreferenz keine Ausnahmen auszulösen, da dies keine Rolle spielt, da die Methode statisch ist.
Malcolm

13
@ JonofAllTrades: Die eigentliche Frage ist, warum die Entscheidung getroffen wurde, statische Mitglieder als Instanz aufrufen zu lassen ... Für mich scheint dies nur zu Verwirrung und weniger lesbarem Code zu führen.
Falanwe

2
@Falanwe: Einverstanden, und es ist ein Konstrukt, für das ich keine Notwendigkeit hatte, obwohl ich meistens in .NET arbeite, wo es nicht erlaubt ist. Ich denke, Sie möchten möglicherweise die entsprechende statische Methode einer Unterklasse aufrufen, wenn Sie einen Verweis auf eine übergeordnete Klasse erhalten.

8
@Falanwe Dies ist zulässig, löst jedoch in Eclipse eine Warnung aus: "Auf das statische Feld Main.value sollte statisch zugegriffen werden". Zumindest diejenigen von uns, die wählerisch in Bezug auf Warnungen sind (wie ich), würden einen solchen Code vermeiden.
Artyom

19

Denn wie Sie sagten, sind statische Felder keiner Instanz zugeordnet.

Die Möglichkeit, über eine Instanzreferenz (wie Sie es tun) auf statische Felder zuzugreifen, ist lediglich ein syntaktischer Zucker und hat keine zusätzliche Bedeutung.
Ihr Code wird zu kompiliert

main.getNull(); 
Main.value

7
Ich würde es syntaktischen Zucker nennen, eher wie syntaktischen Sägemehl;)
Stephen Swensen

3

Wenn Sie zur Kompilierungszeit auf eine statische Variable oder Methode mit Objekten zugreifen, wird diese in den Klassennamen konvertiert. z.B:

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

Der Wert der statischen Variablen wird gedruckt, da er zur Kompilierungszeit in konvertiert wird

System.out.println(Main.value);

Beweis:

Laden Sie den Dekompiler herunter und dekompilieren Sie Ihre .class-Datei in eine .java-Datei. Sie können sehen, dass alle statischen Methoden oder variablenbezogenen Objektnamen automatisch durch den Klassennamen ersetzt werden.


3
  1. Der Zugriff auf ein staticMitglied mit dem Klassennamen ist legal, es wurde jedoch nicht geschrieben, dass staticmit der Objektreferenzvariablen nicht auf das Mitglied zugegriffen werden kann. Also funktioniert es hier drüben.

  2. Eine nullObjektreferenzvariable kann auf eine staticKlassenvariable zugreifen , ohne beim Kompilieren oder zur Laufzeit eine Ausnahme auszulösen.


2

Statische Variable und Methode gehören immer zur Klasse. Wenn wir also ein Objekt erstellen, werden nur nicht statische Variablen und Methoden zusammen mit dem Objekt gehäuft, aber statisch befindet sich im Methodenbereich mit Klasse. Wenn wir versuchen, auf eine statische Variable oder Methode zuzugreifen, wird diese in einen Klassennamen, eine Punktvariable oder einen Methodennamen konvertiert.

Weitere Informationen finden Sie unter dem folgenden Link.

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.