05.04 non static cannot be referenced from a static context

Vor allem beim Einstieg in die Programmierer-Welt kann es vorkommen, dass Sie den Compiler-Fehler non static method/variable cannot be referenced from a static context beim Kompilieren erhalten. Dies ist meistens dann der Fall, wenn Sie sich noch nicht mit Objekt-Orientierung (insbesondere mit dem Stichwort static) beschäftigt, oder sie noch nicht 100%ig verstanden haben. Dieses Kapitel hilft Ihnen beim Verständnis, warum dieser Fehler auftritt und wie Sie Ihren Code ausbessern können.

Dieser Fehler tritt immer dann auf, wenn Sie von einem statischen Block auf eine nicht statische Referenz (Objekt-Attribut, Objekt-Methode, …) zugreifen möchten. Versuchen Sie bspw. diese Klasse zu kompilieren:

public class StaticTest {

  private int var = 4;

  public static void main(String[] args) {
    doSomethingCool();
    System.out.println(var);
    new MyClass();
  }

  public void doSomethingCool() {
    System.out.println("I'm doing something cool!");
  }

  public class MyClass {}
}

Sie werden folgende Fehlermeldung vom Compiler erhalten:

StaticTest.java:6: non-static method doSomethingCool() cannot be referenced from a static context
    doSomethingCool();
    ^
StaticTest.java:7: non-static variable var cannot be referenced from a static context
    System.out.println(var);
                       ^
StaticTest.java:8: non-static variable this cannot be referenced from a static context
    new MyClass();
    ^
3 errors

Der umgekehrte Weg ist übrigens ohne Probleme möglich. Von einer nicht statischen Methode könnte bspw. auf eine statische Variable zugegriffen werden. Dies sollten Sie aber nicht über ein Objekt, sondern über die Klasse erledigen.

// Funktioniert, aber nicht optimal
MyClass mc = new MyClass();
...
System.out.println(mc.MY_PUBLIC_STATIC_VAR);
// saubere Implementierung
System.out.println(MyClass.MY_PUBLIC_STATIC_VAR);

Kommen wir zurück zu unserem Problem. Warum tritt dieser Fehler überhaupt auf? Dies ist relativ einfach zu erklären. Betrachten wir unsere Main-Methode. Sie ist, wie am Schlüsselwort static zu erkennen, statisch und somit aufrufbar, ohne ein Objekt dieser Klasse zu erstellen (siehe Kapitel 04.03.07 Verwendung von static). Sehen Sie sich nun die Methode doSomethingCool an. Diese Methode wurde nicht mit dem static-Schlüsselwort versehen, und ist folglich eine Objekt-Methode. Wie Sie im Kapitel über Objekt-Orientierung gelernt haben, können Sie Objekt-Methoden nur dann ansprechen, wenn Sie auch ein Objekt von der implementierenden Klasse vorliegen haben. Selbes gilt für das Objekt-Attribut var und die Innere Klasse MyClass.

Rufen Sie sich an dieser Stelle den Zusammenhang zwischen Klassen und Objekten in den Kopf. Ein Objekt ist die Repräsentation einer wirklichen Sache wie z. B. einem Motor. Eine Klasse hingegen nur die Strukturbeschreibung bzw. der Bauplan eines Objekts, z. B. eine Anleitung, wie man einen Motor baut. Wenn Sie jetzt bspw. die Größe des Hubraums eines Motors abfragen möchten, dann können Sie diese Frage natürlich nicht an den Bauplan des Motors stellen (nach diesem Bauplan können ja auch mehrere Motoren mit unterschiedlich großem Hubraum gebaut werden), sondern benötigen wirklich ein Objekt Ihres Motors. Verdeutlichen wir das an einem praktischen Beispiel:

Sie haben eine Klasse Motor, eine Klasse Mechaniker, welche Motoren baut, und eine Klasse Welt, die unsere Main-Methode enthält.

public class Motor {

  private float hubraum;

  public void setHubraum(float hubraum) {
    this.hubraum = hubraum;
  }

  public float getHubraum() {
    return this.hubraum;
  }

}
public class Mechaniker {

  public Motor baueMotor(float hubraum) {
    Motor m = new Motor();
    m.setHubraum(hubraum);
    return m;
  }
}
public class Welt {

  public static void main(String[] args) {
  
    Mechaniker horst = new Mechaniker();
    Motor m1 = horst.baueMotor(1.6f);
    Motor m2 = horst.baueMotor(3f);
    
    System.out.println(m1.getHubraum());
    System.out.println(m2.getHubraum());
  }
}

Dies lässt sich ohne Probleme kompilieren. Wenn Sie jetzt allerdings kein neues Mechaniker- oder Motor-Objekt erzeugen, würde es wieder zu unserer Fehlermeldung kommen, da wir ja nur auf den Bauplan, nicht aber auf das eigentliche Objekt zugreifen.

public class Welt {

  public static void main(String[] args) {
  
    Mechaniker.baueMotor(1.6f);
    System.out.println(Motor.getHubraum());
  }
}
Welt.java:5: non-static method baueMotor(float) cannot be referenced from a static context
    Mechaniker.baueMotor(1.6f);
              ^
Welt.java:6: non-static method getHubraum() cannot be referenced from a static context
    System.out.println(Motor.getHubraum());
                            ^
2 errors

Fehlerbehebung

Zuerst müssen Sie sich klar machen, was für Ihre Anwendung am sinnvollsten ist. Wollen Sie wirklich statische Methoden und Attribute verwenden? Dann ergänzen Sie das static-Stichwort an den entsprechenden Stellen. Meistens ist es aber der Fall, dass ein Designfehler vorliegt. Sie müssen sich also an geeigneter Stelle ein neues Objekt erzeugen und auf dieses zugreifen.

Schreibe einen Kommentar