non-static method can't be referenced from a static context

Status
Nicht offen für weitere Antworten.
B

Beni

Gast
non-static method can't be referenced from a static context
Dieser Fehler tritt oft auf. Die Lösung ist einfach, nur dran denken muss man.
Der folgende Text wird zuerst ein bisschen Theorie vermitteln, und am Schluss Standartfehler Nr. 13 lösen :wink:

Es gibt zwei Arten von Methoden: statische und nicht-statische.

Statische Methoden, erkennbar an dem Wort static, gehören zu einer Klasse (manchmal sagt man auch "ein Typ"), und haben keinen Bezug zu dem Objekt, welches die Klasse darstellt.

Nicht-statische Methoden (die ohne static) gehören zu einem Objekt, und können ohne ein Objekt nicht funktionieren.

Wenn man nun aus einer statischen Methoden eine Methode aufruft, welche nicht statisch ist, muss man dieser anderen Methode genau sagen, zu welchem Objekt sie gehört.

Einige Beispiele mögen das verdeutlichen:

Statisch - Nicht-statisch
Aus einer statischen Methode kann man auch eine Nicht-statische Methode aufrufen. Das hört sich verwirrend an, ist aber eigentlich grausam banal:
Java:
public class Main{
	public static void main(String[] args) {
		// Wir sind hier in einer statischen Methode

		// Jetzt erstellen wir erstmal ein paar Objekte
		Test fritz = new Test( "Fritz" );
		Test hans = new Test( "Hans" );

		// und hier wird zweimal eine nicht-statische Methode aufgerufen.
		fritz.doSomething();
		hans.doSomething();
	}
}
Java:
public class Test{
	private String name;
	public Test( String name ){
		// Das ist gar keine Methode, das ist ein Konstruktor :-)
		this.name = name;
	}
	public void doSomething(){
		// Das ist eine nicht-statische Methode
		System.out.println( "Hallo :-), ich bin " + name );
	}
}

Falls dieser Code Mühe bereitet: entweder ist es Zeit wiedereinmal zu schlafen, oder Du solltest wirklich ein Anfängerbuch lesen! Für letzteres kann ich das Javabuch und Java ist auch eine Insel empfehlen.

Vereinfachen?
Man könnte ja vielleicht dieses public static void main direkt in das "Test" schreiben:
Java:
public class Test{
	public static void main( String[] args ){
		// Ausgabe des Namens
		doSomething();
	}

	private String name;
	public Test( String name ){
		// Das ist gar keine Methode, das ist ein Konstruktor :-)
		this.name = name;
	}
	public void doSomething(){
		// Das ist eine nicht-statische Methode
		System.out.println( "Hallo :-), ich bin " + name );
	}
}

Das wird nicht funktionieren!
Nur schon eine einfache ßberlegung zeigt uns, dass das nicht aufgehen kann: doSomething soll den Namen ausgeben... welchen Namen? Wir haben gar niergends einen Namen hingeschrieben!

Ein weiterer Versuch
Diesmal sind wir besser, zuerst definieren wir einen Namen.

Java:
public class Test{
	public static void main( String[] args ){
		new Test( "Heinz" );
		doSomething();
	}

	private String name;
	public Test( String name ){
		// Das ist gar keine Methode, das ist ein Konstruktor :-)
		this.name = name;
	}
	public void doSomething(){
		// Das ist eine nicht-statische Methode
		System.out.println( "Hallo :-), ich bin " + name );
	}
}

Auch das funktioniert nicht!
Weil doSomething nicht weiss, auf welches Objekt es sich bezieht. Sicher, da existiert ein Objekt des Types "Test", aber woher soll doSomething wissen, dass wir dieses Objekt meinen?

War das ziemlich unklar?
Dann betrachten wir mal die nächste Variante:
Java:
public class Test{
	public static void main( String[] args ){
		new Test( "Heinz" );
		new Test( "Werner" );
		doSomething();
	}

	private String name;
	public Test( String name ){
		// Das ist gar keine Methode, das ist ein Konstruktor :-)
		this.name = name;
	}
	public void doSomething(){
		// Das ist eine nicht-statische Methode
		System.out.println( "Hallo :-), ich bin " + name );
	}
}

Was würde dieses Programm wohl ausgeben? Keine Ahnung? Das ist auch gut, denn es ist wirklich nicht klar. Bezieht sich das doSomething auf Heinz oder auf Werner? Es ist wohl ganz gut, dass hier der Compiler einen Fehler ausgiebt.

Die Lösung
Die Lösung des Problemes ist, dass wir bei jedem Aufruf von "doSomething" angeben, auf welches Objekt (Heinz oder Werner) es sich bezieht:
Java:
public class Test{
	public static void main( String[] args ){
		Test heinz = new Test( "Heinz" );
		Test werner = new Test( "Werner" );

		heinz.doSomething();
		werner.doSomething();
	}

	private String name;
	public Test( String name ){
		// Das ist gar keine Methode, das ist ein Konstruktor :-)
		this.name = name;
	}
	public void doSomething(){
		// Das ist eine nicht-statische Methode
		System.out.println( "Hallo :-), ich bin " + name );
	}
}

Irgendwas bemerkt? Richtig: das hatten wir schon zu Beginn. Die vermeindliche Abkürzung war keine, die statische Methode main kann überall stehen, sie hat keinen Bezug zu irgendwelchen Objekten (selbst wenn das Objekte desjenigen Types sind, in der die statische Methode steht).
Aber die paar Beispiele haben auch gezeigt, wieso eine nicht-statische Methode, die zu einem Objekt gehört, einen Bezug zu einem Objekt benötigen.
 
B

bygones

Gast
Nur eine kleine Anmerkung:
Der umgekehrte Weg ist natürlich möglich, d.h. aus einem nicht-statischen Methode eine statische Variable oder Methode aufzurufen !

Java:
public class Test {
  private static int number = 0;

  public void doSomething() {
    number ++;
     
    doStatic();
  }

  public static void doStatic() {
   // do it
  }
}
 

Illuvatar

Top Contributor
Noch eine Anmerkung zu bygones:

Nach den Coding Conventions von Sun ist dieses "aus einem Objekt einfach eine statische Methode aufrufen", wie es bygones gezeigt hat, ein schlechter Stil. Man sollte statische Methoden/ immer mit dem Klassennamen aufrufen, also so:
Java:
public class Test { 
  private static int number = 0; 

  public void doSomething() { 
    number ++; 
      
    Test.doStatic(); 
  } 

  public static void doStatic() { 
   // do it 
  } 
}

Das gleiche gilt für Variablen. Statt diesem leider häufig verwendeten Code
Java:
JFrame jf = new JFrame("Test");
jf.setDefaultCloseOperation (jf.DO_NOTHING_ON_CLOSE);

sollte man also diesen verwenden:
Java:
JFrame jf = new JFrame("Test");
jf.setDefaultCloseOperation (JFrame.DO_NOTHING_ON_CLOSE);
 
Status
Nicht offen für weitere Antworten.

Oben