La variabile non statica non può essere referenziata da un contesto statico


288

Ho scritto questo codice di prova:

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

Ma dà il seguente errore:

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

Come posso ottenere i miei metodi per riconoscere le mie variabili di classe?


Cerca di evitare l'uso di elettricità statica quando possibile. È possibile scrivere un programma completo, tutto statico, proprio come in C. Ma non sarà molto buono. Cerca di usare Java come dovrebbe essere usato, come linguaggio orientato agli oggetti.
Erick G. Hagstrom,

Risposte:


294

È necessario comprendere la differenza tra una classe e un'istanza di quella classe. Se vedi un'auto per strada, sai immediatamente che è un'auto anche se non riesci a vedere quale modello o tipo. Questo perché si confronta ciò che si vede con la classe "auto". La classe contiene quale è simile a tutte le auto. Pensalo come un modello o un'idea.

Allo stesso tempo, l'auto che vedi è un'istanza della classe "auto" poiché ha tutte le proprietà che ti aspetti: c'è qualcuno che la guida, ha un motore, ruote.

Quindi la classe dice "tutte le auto hanno un colore" e l'istanza dice "questa macchina specifica è rossa".

Nel mondo OO, si definisce la classe e all'interno della classe, si definisce un campo di tipo Color . Quando la classe viene istanziata (quando crei un'istanza specifica), la memoria è riservata al colore e puoi assegnare a questa istanza specifica un colore. Poiché questi attributi sono specifici, non sono statici.

I campi e i metodi statici sono condivisi con tutte le istanze. Sono per valori specifici della classe e non di un'istanza specifica. Per i metodi, di solito si tratta di metodi di supporto globali (come Integer.parseInt()). Per i campi, di solito sono costanti (come i tipi di auto, cioè qualcosa in cui hai un set limitato che non cambia spesso).

Per risolvere il problema, è necessario creare un'istanza di un'istanza (creare un oggetto) della classe in modo che il runtime possa riservare memoria per l'istanza (altrimenti, istanze diverse si sovrascriverebbero a vicenda che non si desidera).

Nel tuo caso, prova questo codice come blocco iniziale:

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
}

Il nuovo main()metodo crea un'istanza della classe che contiene (sembra strano ma poiché main()viene creato con la classe anziché con l'istanza, può farlo) e quindi chiama un metodo di istanza ( run()).


Sto spiegando questo al momento al nostro nuovo collega - grazie per questa grande spiegazione. Questa dovrebbe essere la risposta accettabile.
Supahupe

83

I campi e i metodi statici sono collegati alla classe stessa e non alle sue istanze. Se si dispone di una classe A, un metodo di 'normale' b, e un metodo statico c, e fate un'istanza adella classe A, le chiamate verso A.c()e a.b()sono validi. Il metodo c()non ha idea dell'istanza collegata, quindi non può utilizzare campi non statici.

La soluzione per te è rendere i tuoi campi statici o i tuoi metodi non statici. Il tuo principale potrebbe apparire così:

class Programm {

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

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

54

La staticparola chiave modifica il ciclo di vita di un metodo o di una variabile all'interno di una classe. Un staticmetodo o una variabile vengono creati al momento del caricamento di una classe. Un metodo o una variabile che non viene dichiarato come staticviene creato solo quando la classe viene istanziata come oggetto, ad esempio utilizzando l' newoperatore.

Il ciclo di vita di una classe, in termini generali, è:

  1. il codice sorgente per la classe viene scritto creando un modello o modello o timbro che può quindi essere utilizzato per
  2. creare un oggetto con il new operatore utilizzando la classe per creare un'istanza della classe come oggetto reale e, una volta terminato, con l'oggetto
  3. distruggere l'oggetto recuperando le risorse in suo possesso come la memoria durante la garbage collection.

Per avere un punto di ingresso iniziale per un'applicazione, Java ha adottato la convenzione secondo cui il programma Java deve avere una classe che contenga un metodo con un nome concordato o speciale. Questo metodo speciale è chiamato main(). Poiché il metodo deve esistere indipendentemente dal fatto che la classe contenente il metodo principale sia stata istanziata o meno, il main()metodo deve essere dichiarato con il staticmodificatore in modo che non appena la classe viene caricata, il main()metodo sia disponibile.

Il risultato è che quando si avvia l'applicazione Java da una riga di comando come java helloworlduna serie di azioni, si verificano. Prima di tutto una Java Virtual Machine viene avviata e inizializzata. Successivamente il file helloworld.class contenente il codice Java compilato viene caricato nella Java Virtual Machine. Quindi la Java Virtual Machine cerca un metodo nella helloworldclasse chiamata main(String [] args). questo metodo deve essere statictale da esistere anche se la classe non è stata realmente istanziata come oggetto. Java Virtual Machine non crea un'istanza della classe creando un oggetto dalla classe. Carica solo la classe e avvia l'esecuzione con il main()metodo.

Quindi è necessario creare un'istanza della classe come oggetto e quindi è possibile accedere ai metodi e alle variabili della classe che non sono stati dichiarati con il staticmodificatore. Una volta avviato il programma Java con la main()funzione, è possibile utilizzare qualsiasi variabile o metodo che abbia il modificatore distatic poiché esiste come parte della classe da caricare.

Tuttavia, quelle variabili e metodi della classe che sono al di fuori del main()metodo che non hanno il staticmodificatore non possono essere usati fino a quando un'istanza della classe non è stata creata come oggetto all'interno del main()metodo. Dopo aver creato l'oggetto è quindi possibile utilizzare le variabili e i metodi dell'oggetto. Un tentativo di utilizzare le variabili e i metodi della classe che non hanno il staticmodificatore senza passare attraverso un oggetto della classe viene rilevato dal compilatore Java al momento della compilazione e contrassegnato come errore.

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

Analizziamo prima il tuo programma .. Nel tuo programma, il tuo primo metodo è main(), e tienilo a mente che è il metodo statico ... Quindi dichiari la variabile locale per quel metodo (compareCount, basso, alto, ecc.). L'ambito di questa variabile è solo il metodo dichiarato, indipendentemente dal fatto che sia un metodo statico o non statico. Quindi non puoi usare quelle variabili al di fuori di quel metodo. Questo è l'errore di base che hai commesso.

Quindi arriviamo al punto successivo. Hai detto che statico ti sta uccidendo. (Potrebbe ucciderti, ma dà vita solo al tuo programma !!) Per prima cosa devi capire la cosa di base. * Il metodo statico chiama solo il metodo statico e utilizza solo la variabile statica. * La variabile statica o il metodo statico non dipendono da nessuna istanza di quella classe. (ad esempio, se si modifica uno stato della variabile statica, si rifletterà in tutti gli oggetti della classe) * Per questo motivo la si chiama come variabile di classe o metodo di classe. E molto di più c'è sulla parola chiave "statica". Spero ora che tu abbia avuto l'idea. Innanzitutto cambia l'ambito della variabile e dichiaralo come statico (per poterlo utilizzare in metodi statici).

E il consiglio per te è: hai frainteso l'idea della portata delle variabili e delle funzionalità statiche. Fatti un'idea chiara a riguardo.


11

La cosa fondamentale è che le variabili statiche oi metodi statici sono a livello di classe. Le variabili o i metodi a livello di classe vengono caricati prima dei metodi o delle variabili a livello di istanza e ovviamente l'elemento che non viene caricato non può essere utilizzato. Quindi il compilatore java non consente che le cose da gestire in fase di esecuzione si risolvano in fase di compilazione. Ecco perché ti dà errori che non possono essere riferiti al contesto statico. Hai solo bisogno di leggere su Ambito di livello di classe, Ambito di livello di istanza e Ambito locale.


8

Per poter accedervi dai tuoi metodi statici, devono essere variabili membro statiche, in questo modo:

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

Ora puoi aggiungere / usare istanze con nel metodo

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

Esempio molto solido che ho usato come modello per revisionare un file src complesso in una struttura adeguata.
XMAN,

3

Proverò a spiegarti la cosa statica. Innanzitutto le variabili statiche non appartengono a nessuna istanza particolare della classe. Sono riconosciuti con il nome della classe. I metodi statici di nuovo non appartengono di nuovo a nessuna istanza particolare. Possono accedere solo alle variabili statiche. Immagina di chiamare MyClass.myMethod () e myMethod è un metodo statico. Se usi variabili non statiche all'interno del metodo, come diavolo saprebbe quali variabili usare? Ecco perché è possibile utilizzare da metodi statici solo variabili statiche. Ripeto ancora, NON appartengono a nessun caso particolare.


2
  • La prima cosa è conoscere la differenza tra un'istanza di una classe e la classe stessa. Una classe modella alcune proprietà e il comportamento dell'insieme nel contesto di tali proprietà. Un'istanza definirà valori specifici per tali proprietà.

  • Tutto ciò che è associato alla parola chiave statica è disponibile nel contesto della classe anziché nel contesto di un'istanza della classe

  • Come corollario di quanto sopra

    1. le variabili all'interno di un metodo non possono essere statiche
    2. campi statici e metodi devono essere invocati utilizzando il nome della classe, ad esempio MyProgram7.main (...)
  • La durata di un campo / metodo statico è equivalente alla durata dell'applicazione

Ad esempio, l'auto ha il colore della proprietà ed esibisce il comportamento "movimento". Un'istanza della vettura sarebbe un Maggiolino rosso in movimento a 25 km / h.

Ora una proprietà statica dell'auto sarebbe il numero di ruote (4) sulla strada, e questo si applicherebbe a tutte le auto.

HTH


1

ClassLoader è responsabile del caricamento dei file di classe. Vediamo cosa succede quando scriviamo le nostre classi.

Esempio 1:

class StaticTest {

      static int a;
      int b;
      int c;
}

Ora possiamo vedere che la classe "StaticTest" ha 3 campi, ma in realtà non esiste alcuna variabile membro b, c. Ma perché ???. OK, per non vedere. Qui b, c sono variabili di istanza. Poiché la variabile di istanza ottiene la memoria al momento della creazione dell'oggetto. Quindi qui b, c non stanno ancora ricevendo memoria. Ecco perché non esiste esistenza di b, c. Quindi esiste solo l'esistenza di a. Per ClassLoader ha solo una informazione su a. ClassLoader non riconosce ancora b, c perché l'oggetto non è ancora istanziato.

Vediamo un altro esempio: Esempio 2:

class StaticTest {

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


      public static void main(String []cmd) {

             display();       
      }

}

Ora, se proviamo a compilare questo compilatore di codice, verrà visualizzato l'errore CE. CE: non è possibile fare riferimento a un metodo non statico display () da un contesto statico.

Ora per ClassLoader sembra che:

class StaticTest {

      public static void main(String []cmd) {

             display();       
      }

}

Nell'esempio 2 l'errore CE è perché chiamiamo metodo non statico da un contesto statico. Pertanto, ClassLoader non è in grado di riconoscere il metodo display () al momento della compilazione. Si è verificato un errore durante la compilazione.


Probabilmente hai inviato la tua risposta per caso prima di riuscire a finirla? Modifica e aggiungi il contenuto mancante, grazie!
Plamut,

1

Prima di chiamare un metodo di istanza o una variabile di istanza Ha bisogno di un oggetto (Istanza). Quando la variabile di istanza viene chiamata dal compilatore del metodo statico non sa a quale oggetto appartiene questa variabile. Perché i metodi statici non hanno un oggetto (solo una copia sempre). Quando si chiama una variabile di istanza o metodi di istanza dal metodo di istanza, fa riferimento athis all'oggetto. Significa che la variabile appartiene a qualunque oggetto creato e ogni oggetto ha la propria copia dei metodi e delle variabili di istanza.

Le variabili statiche sono contrassegnate come statice le variabili di istanza non hanno una parola chiave specifica.


0

Questo è un po 'diff per spiegare la parola chiave statica per tutti i principianti.
Lo imparerai chiaramente quando lavori di più con Classi e Oggetti.

| * | Statico: gli elementi statici possono essere chiamati con il nome della classe
Se si osserva nei codici, alcune funzioni vengono chiamate direttamente con nomi di classi come

NamCls.NamFnc();

System.out.println();

Questo perché NamFnc e println verranno dichiarati usando la parola chiave static prima di loro.

| * | Non statico: gli elementi non statici possono essere chiamati con la variabile di classe
Se non è statico, è necessaria una variabile della classe,
inserire un punto dopo la variabile di classe e
quindi chiamare la funzione.

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


Di seguito il codice ti spiega chiaramente

| * | Funzione statica e non statica in classe:

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


| * | Classe statica e non statica all'interno di una classe:

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