Nicht statische Variablen können nicht aus einem statischen Kontext referenziert werden


288

Ich habe diesen Testcode geschrieben:

class MyProgram
{
    int count = 0;
    public static void main(String[] args)
    {
        System.out.println(count);
    }
}

Aber es gibt den folgenden Fehler:

Main.java:6: error: non-static variable count cannot be referenced from a static context
        System.out.println(count);
                           ^

Wie erhalte ich meine Methoden zum Erkennen meiner Klassenvariablen?


Vermeiden Sie nach Möglichkeit die Verwendung von Statik. Sie können ein komplettes Programm schreiben, alles statisch, genau wie in C. Aber es wird nicht sehr gut. Versuchen Sie, Java so zu verwenden, wie es verwendet werden soll, als objektorientierte Sprache.
Erick G. Hagstrom

Antworten:


294

Sie müssen den Unterschied zwischen einer Klasse und einer Instanz dieser Klasse verstehen. Wenn Sie ein Auto auf der Straße sehen, wissen Sie sofort, dass es sich um ein Auto handelt, auch wenn Sie nicht sehen können, welches Modell oder welcher Typ. Dies liegt daran, dass Sie das, was Sie sehen, mit der Klasse "Auto" vergleichen. Die Klasse enthält, die allen Autos ähnlich ist. Betrachten Sie es als Vorlage oder Idee.

Gleichzeitig ist das Auto, das Sie sehen, eine Instanz der Klasse "Auto", da es alle Eigenschaften hat, die Sie erwarten: Es fährt jemand, es hat einen Motor, Räder.

Die Klasse sagt also "alle Autos haben eine Farbe" und die Instanz sagt "dieses spezielle Auto ist rot".

In der OO-Welt definieren Sie die Klasse und innerhalb der Klasse definieren Sie ein Typfeld Color. Wenn die Klasse instanziiert wird (wenn Sie eine bestimmte Instanz erstellen), ist der Speicher für die Farbe reserviert, und Sie können dieser bestimmten Instanz eine Farbe geben. Da diese Attribute spezifisch sind, sind sie nicht statisch.

Statische Felder und Methoden werden von allen Instanzen gemeinsam genutzt. Sie gelten für klassenspezifische Werte und nicht für eine bestimmte Instanz. Bei Methoden sind dies normalerweise globale Hilfsmethoden (wie Integer.parseInt()). Für Felder sind es normalerweise Konstanten (wie Autotypen, dh etwas, bei dem Sie eine begrenzte Menge haben, die sich nicht oft ändert).

Um Ihr Problem zu lösen, müssen Sie eine Instanz Ihrer Klasse instanziieren (ein Objekt erstellen), damit die Laufzeit Speicher für die Instanz reservieren kann (andernfalls würden sich verschiedene Instanzen gegenseitig überschreiben, was Sie nicht möchten).

Versuchen Sie in Ihrem Fall diesen Code als Startblock:

public static void main (String[] args)
{
    try
    {
        MyProgram7 obj = new MyProgram7 ();
        obj.run (args);
    }
    catch (Exception e)
    {
        e.printStackTrace ();
    }
}

// instance variables here

public void run (String[] args) throws Exception
{
    // put your code here
}

Die neue main()Methode erstellt eine Instanz der Klasse, die sie enthält (klingt seltsam, aber da main()sie mit der Klasse anstatt mit der Instanz erstellt wird, kann sie dies tun) und ruft dann eine Instanzmethode ( run()) auf.


Ich erkläre dies im Moment unserem neuen Kollegen - danke für diese großartige Erklärung. Dies sollte die akzeptierte Antwort sein.
Supahupe

83

Statische Felder und Methoden sind mit der Klasse selbst und nicht mit ihren Instanzen verbunden. Wenn Sie eine Klasse A, eine 'normale' Methode bund eine statische Methode chaben und eine Instanz aIhrer Klasse erstellen A, sind die Aufrufe von A.c()und a.b()gültig. Die Methode c()hat keine Ahnung, welche Instanz verbunden ist, daher kann sie keine nicht statischen Felder verwenden.

Die Lösung für Sie besteht darin, dass Sie entweder Ihre Felder statisch oder Ihre Methoden nicht statisch machen. Sie könnten dann hauptsächlich so aussehen:

class Programm {

    public static void main(String[] args) {
        Programm programm = new Programm();
        programm.start();
    }

    public void start() {
        // can now access non-static fields
    }
}

54

Das staticSchlüsselwort ändert den Lebenszyklus einer Methode oder Variablen innerhalb einer Klasse. Eine staticMethode oder Variable wird zum Zeitpunkt des Ladens einer Klasse erstellt. Eine Methode oder Variable, die nicht als deklariert staticist, wird nur erstellt, wenn die Klasse beispielsweise mithilfe des newOperators als Objekt instanziiert wird .

Der Lebenszyklus einer Klasse ist im Großen und Ganzen:

  1. Der Quellcode für die Klasse wird so geschrieben, dass eine Vorlage, ein Muster oder ein Stempel erstellt wird, die dann verwendet werden können
  2. Erstellen Sie ein Objekt mit dem new Operator , indem Sie die Klasse verwenden, um eine Instanz der Klasse als tatsächliches Objekt zu und dann, wenn Sie mit dem Objekt fertig sind
  3. Zerstören Sie das Objekt, indem Sie die Ressourcen zurückgewinnen, die es enthält, z. B. Speicher während der Speicherbereinigung.

Um einen ersten Einstiegspunkt für eine Anwendung zu haben, hat Java die Konvention übernommen, dass das Java-Programm eine Klasse haben muss, die eine Methode mit einem vereinbarten oder speziellen Namen enthält. Diese spezielle Methode wird aufgerufen main(). Da die Methode existieren muss, unabhängig davon, ob die Klasse, die die Hauptmethode enthält, instanziiert wurde oder nicht, main()muss die Methode mit dem staticModifikator deklariert werden , damit die main()Methode verfügbar ist, sobald die Klasse geladen wird.

Das Ergebnis ist, dass beim Starten Ihrer Java-Anwendung über eine Befehlszeile beispielsweise java helloworldeine Reihe von Aktionen ausgeführt werden. Zunächst wird eine Java Virtual Machine gestartet und initialisiert. Als nächstes wird die Datei helloworld.class, die den kompilierten Java-Code enthält, in die Java Virtual Machine geladen. Anschließend sucht die Java Virtual Machine in der helloworldaufgerufenen Klasse nach einer Methode main(String [] args). Diese Methode muss staticso sein, dass sie existiert, obwohl die Klasse nicht tatsächlich als Objekt instanziiert wurde. Die Java Virtual Machine erstellt keine Instanz der Klasse, indem sie ein Objekt aus der Klasse erstellt. Es lädt nur die Klasse und startet die Ausführung bei der main()Methode.

Sie müssen also eine Instanz Ihrer Klasse als Objekt erstellen und können dann auf die Methoden und Variablen der Klasse zugreifen, die nicht mit dem staticModifikator deklariert wurden . Sobald Ihr Java-Programm mit der main()Funktion gestartet wurde, können Sie alle Variablen oder Methoden verwenden, die den Modifikator habenstatic da sie als Teil der zu ladenden Klasse vorhanden sind.

Die Variablen und Methoden der Klasse, die sich außerhalb der main()Methode befinden und nicht über den staticModifikator verfügen, können jedoch erst verwendet werden, wenn eine Instanz der Klasse als Objekt innerhalb der main()Methode erstellt wurde. Nach dem Erstellen des Objekts können Sie die Variablen und Methoden des Objekts verwenden. Ein Versuch, die Variablen und Methoden der Klasse zu verwenden, die den staticModifikator nicht haben, ohne ein Objekt der Klasse zu durchlaufen, wird vom Java-Compiler zur Kompilierungszeit abgefangen und als Fehler gekennzeichnet.

import java.io.*;

class HelloWorld {
    int myInt;      // this is a class variable that is unique to each object
    static int myInt2;  // this is a class variable shared by all objects of this class

    static void main (String [] args) {
        // this is the main entry point for this Java application
        System.out.println ("Hello, World\n");
        myInt2 = 14;    // able to access the static int
        HelloWorld myWorld = new HelloWorld();
        myWorld.myInt = 32;   // able to access non-static through an object
    }
}

11

Lassen Sie uns zuerst Ihr Programm analysieren. In Ihrem Programm ist Ihre erste Methode main() , und denken Sie daran, dass es sich um die statische Methode handelt. Dann deklarieren Sie die lokale Variable für diese Methode (compareCount, low, high usw.). Der Bereich dieser Variablen ist nur die deklarierte Methode, unabhängig davon, ob es sich um eine statische oder eine nicht statische Methode handelt. Sie können diese Variablen also nicht außerhalb dieser Methode verwenden. Dies ist der grundlegende Fehler, den du gemacht hast.

Dann kommen wir zum nächsten Punkt. Du hast gesagt, statisch bringt dich um. (Es mag dich töten, aber es gibt deinem Programm nur Leben !!) Zuerst musst du die grundlegende Sache verstehen. * Die statische Methode ruft nur die statische Methode auf und verwendet nur die statische Variable. * Statische Variablen oder statische Methoden sind von keiner Instanz dieser Klasse abhängig. (dh wenn Sie einen Status der statischen Variablen ändern, wird dieser in allen Objekten der Klasse wiedergegeben.) * Aus diesem Grund rufen Sie ihn als Klassenvariable oder Klassenmethode auf. Und es gibt noch viel mehr über das Schlüsselwort "statisch". Ich hoffe jetzt kommst du auf die Idee. Ändern Sie zuerst den Bereich der Variablen und deklarieren Sie sie als statisch (um sie in statischen Methoden verwenden zu können).

Und der Rat für Sie lautet: Sie haben die Idee des Umfangs der Variablen und statischen Funktionen falsch verstanden. Machen Sie sich eine klare Vorstellung davon.


11

Das Grundlegende ist, dass statische Variablen oder statische Methoden auf Klassenebene sind. Variablen oder Methoden auf Klassenebene werden vor Methoden oder Variablen auf Instanzebene geladen. Und natürlich kann das, was nicht geladen ist, nicht verwendet werden. Der Java-Compiler, der nicht zulässt, dass die zur Laufzeit zu behandelnden Dinge zur Kompilierungszeit aufgelöst werden. Das ist der Grund, warum es Ihnen Fehler gibt. Nicht statische Dinge können nicht aus dem statischen Kontext referenziert werden. Sie müssen nur Informationen zum Klassenbereich, zum Instanzbereich und zum lokalen Bereich lesen.


8

Um von Ihren statischen Methoden aus auf sie zugreifen zu können, müssen sie statische Elementvariablen sein, wie folgt:

public class MyProgram7 {
  static Scanner scan = new Scanner(System.in);
  static int compareCount = 0;
  static int low = 0;
  static int high = 0;
  static int mid = 0;  
  static int key = 0;  
  static Scanner temp;  
  static int[]list;  
  static String menu, outputString;  
  static int option = 1;  
  static boolean found = false;

  public static void main (String[]args) throws IOException {
  ...

7

Jetzt können Sie Instanzen mit in der Methode hinzufügen / verwenden

public class Myprogram7 {

  Scanner scan;
  int compareCount = 0;
  int low = 0;
  int high = 0;
  int mid = 0;  
  int key = 0;  
  Scanner temp;  
  int[]list;  
  String menu, outputString;  
  int option = 1;  
  boolean found = false;  

  private void readLine() {

  }

  private void findkey() {

  }

  private void printCount() {

  }
  public static void main(String[] args){

    Myprogram7 myprg=new Myprogram7();
    myprg.readLine();
    myprg.findkey();
    myprg.printCount();
  }
}

Sehr solides Beispiel, das ich als Vorlage verwendet habe, um eine komplexe src-Datei in eine richtige Struktur zu überarbeiten.
XMAN

3

Ich werde versuchen, Ihnen die statische Sache zu erklären. Erstens gehören statische Variablen nicht zu einer bestimmten Instanz der Klasse. Sie werden mit dem Namen der Klasse erkannt. Statische Methoden gehören wiederum nicht wieder zu einer bestimmten Instanz. Sie können nur auf statische Variablen zugreifen. Stellen Sie sich vor, Sie rufen MyClass.myMethod () auf und myMethod ist eine statische Methode. Wenn Sie nicht statische Variablen innerhalb der Methode verwenden, wie zum Teufel würde es dann wissen, welche Variablen verwendet werden sollen? Aus diesem Grund können Sie mit statischen Methoden nur statische Variablen verwenden. Ich wiederhole noch einmal, sie gehören NICHT zu einer bestimmten Instanz.


2
  • Das erste ist, den Unterschied zwischen einer Instanz einer Klasse und der Klasse selbst zu kennen. Eine Klasse modelliert bestimmte Eigenschaften und das Verhalten des Ganzen im Kontext dieser Eigenschaften. Eine Instanz definiert bestimmte Werte für diese Eigenschaften.

  • Alles, was an das statische Schlüsselwort gebunden ist, ist im Kontext der Klasse und nicht im Kontext einer Instanz der Klasse verfügbar

  • Als Folge des oben Gesagten

    1. Variablen innerhalb einer Methode können nicht statisch sein
    2. statische Felder und Methoden müssen mit dem Klassennamen aufgerufen werden, zB MyProgram7.main (...)
  • Die Lebensdauer eines statischen Felds / einer statischen Methode entspricht der Lebensdauer Ihrer Anwendung

ZB sagen wir, Auto hat die Eigenschaftsfarbe und zeigt das Verhalten 'Bewegung'. Ein Beispiel für das Auto wäre ein roter Volkswagen Käfer, der mit 25 km / h in Bewegung ist.

Eine statische Eigenschaft des Autos wäre nun die Anzahl der Räder (4) auf der Straße, und dies würde für alle Autos gelten.

HTH


1

Es ist ClassLoader verantwortlich, die Klassendateien zu laden. Mal sehen, was passiert, wenn wir unsere eigenen Klassen schreiben.

Beispiel 1:

class StaticTest {

      static int a;
      int b;
      int c;
}

Jetzt können wir sehen, dass die Klasse "StaticTest" 3 Felder hat. Aber tatsächlich gibt es keine Existenz der Mitgliedsvariablen b, c. Aber warum ???. OK, damit wir nicht sehen. Hier sind b, c Instanzvariablen. Da die Instanzvariable den Speicher zum Zeitpunkt der Objekterstellung erhält. Also hier bekommen b, c noch keinen Speicher. Deshalb gibt es keine Existenz von b, c. Es gibt also nur eine Existenz von a. Für ClassLoader gibt es nur eine Information über a. ClassLoader erkennt b, c noch nicht, da das Objekt noch nicht instanziiert ist.

Sehen wir uns ein anderes Beispiel an: Beispiel 2:

class StaticTest {

      public void display() {
          System.out.println("Static Test");
      }


      public static void main(String []cmd) {

             display();       
      }

}

Wenn wir nun versuchen, diesen Code zu kompilieren, gibt der Compiler einen CE-Fehler aus. CE: Nicht statische Methoden display () können nicht aus einem statischen Kontext referenziert werden.

Für ClassLoader sieht es nun so aus:

class StaticTest {

      public static void main(String []cmd) {

             display();       
      }

}

In Beispiel 2 liegt der CE-Fehler darin, dass wir eine nicht statische Methode aus einem statischen Kontext aufrufen. Daher ist es ClassLoader nicht möglich, die Methode display () zur Kompilierungszeit zu erkennen. Daher ist ein Fehler bei der Kompilierung aufgetreten.


Wahrscheinlich haben Sie Ihre Antwort versehentlich eingereicht, bevor Sie sie fertiggestellt haben? Bitte bearbeiten Sie es und fügen Sie den fehlenden Inhalt hinzu, danke!
Plamut

1

Bevor Sie eine Instanzmethode oder Instanzvariable aufrufen, benötigt sie ein Objekt (Instanz). Wenn die Instanzvariable vom statischen Methodencompiler aufgerufen wird, weiß sie nicht, zu welchem ​​Objekt diese Variable gehört. Weil statische Methoden kein Objekt haben (immer nur eine Kopie). Wenn Sie eine Instanzvariable oder Instanzmethoden von der Instanzmethode aus aufrufen, verweisen Sie auf diethis Objekt. Dies bedeutet, dass die Variable zu jedem erstellten Objekt gehört und jedes Objekt eine eigene Kopie der Instanzmethoden und -variablen hat.

Statische Variablen sind als gekennzeichnet staticund Instanzvariablen haben kein bestimmtes Schlüsselwort.


0

Dies ist etwas schwierig, um das statische Schlüsselwort für alle Anfänger zu erklären.
Sie werden es klar kennenlernen, wenn Sie mehr mit Klassen und Objekten arbeiten.

| * | Statisch: Statische Elemente können mit Klassennamen aufgerufen werden.
Wenn Sie in Codes beobachten, werden einige Funktionen direkt mit Klassennamen wie aufgerufen

NamCls.NamFnc();

System.out.println();

Dies liegt daran, dass NamFnc und println mit dem vor ihnen stehenden Schlüsselwort static deklariert werden.

| * | Nicht statisch: Nicht statische Elemente können mit der Klassenvariablen aufgerufen werden.
Wenn sie nicht statisch ist, benötigen Sie eine Variable der Klasse,
setzen einen Punkt nach der Klassenvariablen und
rufen dann die Funktion auf.

NamCls NamObjVar = new NamCls();
NamObjVar.NamFnc();


Der folgende Code erklärt Sie ordentlich

| * | Statische und nicht statische Funktion in der Klasse:

public class NamCls
{
    public static void main(String[] args)
    {
        PlsPrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamObjVar.PrnFnc("Tst Txt");
    }

    static void PlsPrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }

    void PrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }
}


| * | Statische und nicht statische Klasse innerhalb einer Klasse:

public class NamCls
{
    public static void main(String[] args)
    {
        NamTicCls NamTicVaj = new NamTicCls();
        NamTicVaj.PrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamNicCls NamNicVar = NamObjVar.new NamNicCls();
        NamNicVar.PrnFnc("Tst Txt");
    }

    static class NamTicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }

    class NamNicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }
}
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.