Do zmiennej niestatycznej nie można się odwoływać z kontekstu statycznego


288

Napisałem ten kod testowy:

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

Ale daje następujący błąd:

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

Jak uzyskać metody rozpoznawania zmiennych klas?


W miarę możliwości staraj się unikać używania ładunków statycznych. Państwo może napisać kompletny program, wszystkie statyczne, podobnie jak w C. Ale to nie będzie zbyt dobre. Spróbuj użyć Java w sposób, w jaki ma być używany, jako język obiektowy.
Erick G. Hagstrom,

Odpowiedzi:


294

Musisz zrozumieć różnicę między klasą a instancją tej klasy. Jeśli zobaczysz samochód na ulicy, natychmiast wiesz, że to samochód, nawet jeśli nie możesz zobaczyć, który model lub typ. Jest tak, ponieważ porównujesz to, co widzisz z klasą „samochód”. Klasa zawiera podobne do wszystkich samochodów. Potraktuj to jako szablon lub pomysł.

Jednocześnie samochód, który widzisz, jest przykładem klasy „samochód”, ponieważ ma wszystkie właściwości, których się spodziewasz: ktoś jeździ, ma silnik, koła.

Tak więc klasa mówi „wszystkie samochody mają kolor”, a instancja mówi „ten konkretny samochód jest czerwony”.

W świecie OO definiujesz klasę, a wewnątrz klasy definiujesz pole typu Color. Po utworzeniu instancji klasy (podczas tworzenia określonej instancji) pamięć jest zarezerwowana dla koloru i można nadać tej konkretnej instancji kolor. Ponieważ te atrybuty są specyficzne, nie są one statyczne.

Pola i metody statyczne są wspólne dla wszystkich instancji. Są to wartości specyficzne dla klasy, a nie konkretna instancja. W przypadku metod są to zwykle globalne metody pomocnicze (jak Integer.parseInt()). W przypadku pól są to zwykle stałe (np. Typy samochodów, tj. Coś, co ma ograniczony zestaw, który nie zmienia się często).

Aby rozwiązać problem, musisz utworzyć instancję (utworzyć obiekt) swojej klasy, aby środowisko wykonawcze mogło zarezerwować pamięć dla instancji (w przeciwnym razie różne instancje zastąpiłyby się nawzajem, czego nie chcesz).

W twoim przypadku wypróbuj ten kod jako blok początkowy:

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
}

Nowa main()metoda tworzy instancję klasy, którą zawiera (brzmi dziwnie, ale ponieważ main()została utworzona z klasą zamiast z instancją, może to zrobić), a następnie wywołuje metodę instancji ( run()).


Wyjaśniam to teraz naszemu nowemu koledze - dziękuję za to wspaniałe wyjaśnienie. To powinno odpowiedzieć.
Supahupe

83

Pola i metody statyczne są połączone z samą klasą, a nie z jej instancjami. Jeśli masz klasę A, metodę „normalną” bi metodę statyczną c, i tworzysz instancję aswojej klasy A, wywołania A.c()i a.b()są poprawne. Metoda c()nie ma pojęcia, która instancja jest podłączona, więc nie może używać pól niestatycznych.

Rozwiązaniem jest to, że albo uczynisz swoje pola statycznymi, albo metodami niestatycznymi. Możesz wtedy wyglądać tak:

class Programm {

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

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

54

staticKluczowe modyfikuje cykl sposobu lub zmiennej w klasie. staticMetoda lub zmienna jest utworzony w momencie klasa jest załadowany. Metoda lub zmienna, która nie jest zadeklarowana jako, staticjest tworzona tylko wtedy, gdy klasa jest tworzona jako obiekt, na przykład za pomocą newoperatora.

Ogólny cykl życia klasy to:

  1. kod źródłowy klasy jest zapisywany, tworząc szablon lub wzór lub pieczęć, do których można się następnie przyzwyczaić
  2. utwórz obiekt za pomocą newoperatora za pomocą klasy, aby utworzyć instancję klasy jako rzeczywistego obiektu, a następnie po zakończeniu z tym obiektem
  3. zniszcz obiekt odzyskujący zasoby, takie jak pamięć, podczas wyrzucania elementów bezużytecznych.

Aby mieć początkowy punkt wejścia dla aplikacji, Java przyjęła konwencję, że program Java musi mieć klasę zawierającą metodę o uzgodnionej lub specjalnej nazwie. Ta specjalna metoda jest nazywana main(). Ponieważ metoda musi istnieć bez względu na to, czy utworzona została instancja klasy zawierającej metodę główną, main()metoda musi zostać zadeklarowana za pomocą staticmodyfikatora, aby po załadowaniu klasy main()metoda była dostępna.

Rezultat jest taki, że po uruchomieniu aplikacji Java za pomocą wiersza polecenia, takiego jak java helloworldseria akcji. Przede wszystkim uruchamiana i inicjowana jest wirtualna maszyna Java. Następnie plik helloworld.class zawierający skompilowany kod Java jest ładowany do wirtualnej maszyny Java. Następnie wirtualna maszyna Java szuka metody w helloworldwywoływanej klasie main(String [] args). ta metoda musi być statictaka, aby istniała, nawet jeśli klasa nie została faktycznie utworzona jako obiekt. Wirtualna maszyna Java nie tworzy instancji klasy, tworząc obiekt z klasy. Po prostu ładuje klasę i rozpoczyna wykonywanie przy main()metodzie.

Musisz więc utworzyć instancję swojej klasy jako obiektu, a następnie uzyskać dostęp do metod i zmiennych klasy, które nie zostały zadeklarowane za pomocą staticmodyfikatora. Po uruchomieniu programu Java z main()funkcją możesz użyć dowolnych zmiennych lub metod, które mają modyfikator, staticponieważ istnieją one jako część ładowanej klasy.

Jednak te zmienne i metody klasy, które są poza main()metodą, które nie mają staticmodyfikatora, nie mogą być użyte, dopóki instancja klasy nie zostanie utworzona jako obiekt w ramach main()metody. Po utworzeniu obiektu możesz użyć zmiennych i metod obiektu. Próba użycia zmiennych i metod klasy, które nie mają staticmodyfikatora bez przejścia przez obiekt klasy, jest przechwytywana przez kompilator Java w czasie kompilacji i oznaczana jako błąd.

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

Najpierw przeanalizujmy Twój program. W twoim programie pierwszą metodą jest main()i pamiętaj, że jest to metoda statyczna ... Następnie zadeklaruj zmienną lokalną dla tej metody (CompareCount, low, high itp.). Zakres tej zmiennej jest tylko deklarowaną metodą, niezależnie od tego, czy jest to metoda statyczna czy niestatyczna. Nie możesz więc używać tych zmiennych poza tą metodą. To jest podstawowy błąd, który popełniłeś.

Następnie dochodzimy do następnego punktu. Powiedziałeś, że static cię zabija. (Być może cię zabija, ale ożywia twój program !!) Najpierw musisz zrozumieć podstawową rzecz. * Metoda statyczna wywołuje tylko metodę statyczną i używa tylko zmiennej statycznej. * Zmienna statyczna lub metoda statyczna nie są zależne od żadnego wystąpienia tej klasy. (tzn. jeśli zmienisz dowolny stan zmiennej statycznej, będzie on odzwierciedlał wszystkie obiekty klasy) * Z tego powodu wywołujesz go jako zmienną klasową lub metodę klasową. I wiele więcej jest na temat słowa kluczowego „static”. Mam nadzieję, że teraz masz pomysł. Najpierw zmień zakres zmiennej i zadeklaruj ją jako statyczną (aby móc jej używać w metodach statycznych).

A rada jest dla ciebie: źle zrozumiałeś pojęcie zakresu zmiennych i funkcji statycznych. Dowiedz się o tym jasno.


11

Bardzo podstawową rzeczą jest to, że zmienne statyczne lub metody statyczne są na poziomie klasy. Zmienne lub metody na poziomie klasy są ładowane przed metodami lub zmiennymi na poziomie instancji. Oczywiście nie można użyć rzeczy, która nie jest załadowana. Tak więc kompilator Java, który nie pozwala na obsługę rzeczy w czasie wykonywania, rozwiązuje się w czasie kompilacji. Dlatego daje błąd, niestatyczne rzeczy nie mogą być przywoływane ze statycznego kontekstu. Musisz tylko przeczytać o zakresie na poziomie klasy, zakresie na poziomie instancji i zasięgu lokalnym.


8

Aby móc uzyskać do nich dostęp za pomocą metod statycznych, muszą to być statyczne zmienne składowe, takie jak to:

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

Teraz możesz dodawać / używać instancji w metodzie

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

Bardzo solidny przykład, którego użyłem jako szablonu do zmiany złożonego pliku src w odpowiednią strukturę.
XMAN,

3

Spróbuję wyjaśnić ci statyczną rzecz. Przede wszystkim zmienne statyczne nie należą do żadnego konkretnego wystąpienia klasy. Są rozpoznawane po nazwie klasy. Metody statyczne ponownie nie należą już do żadnej konkretnej instancji. Mogą uzyskać dostęp tylko do zmiennych statycznych. Wyobraź sobie, że wywołujesz MyClass.myMethod (), a myMethod jest metodą statyczną. Jeśli użyjesz niestatycznych zmiennych w metodzie, skąd, u diabła, wiedziałby, jakich zmiennych użyć? Dlatego możesz używać metod statycznych tylko zmiennych statycznych. Powtarzam jeszcze raz, że NIE należą one do żadnej konkretnej instancji.


2
  • Pierwszą rzeczą jest poznanie różnicy między instancją klasy a samą klasą. Klasa modeluje niektóre właściwości i zachowanie całości w kontekście tych właściwości. Instancja zdefiniuje określone wartości dla tych właściwości.

  • Wszystko związane ze statycznym słowem kluczowym jest dostępne w kontekście klasy, a nie w kontekście wystąpienia klasy

  • W następstwie powyższego

    1. zmienne w ramach metody nie mogą być statyczne
    2. pola statyczne i metody muszą być wywoływane przy użyciu nazwy klasy, np. MyProgram7.main (...)
  • Żywotność pola / metody statycznej jest równa żywotności aplikacji

Powiedzmy, że samochód ma kolor właściwości i wykazuje zachowanie „ruch”. Przykładem samochodu byłby czerwony Volkswagen Beetle w ruchu z prędkością 25 km / h.

Teraz statyczną właściwością samochodu byłaby liczba kół (4) na drodze, i dotyczyłoby to wszystkich samochodów.

HTH


1

ClassLoader jest odpowiedzialny za ładowanie plików klas. Zobaczmy, co się stanie, gdy piszemy własne klasy.

Przykład 1:

class StaticTest {

      static int a;
      int b;
      int c;
}

Teraz widzimy, że klasa „StaticTest” ma 3 pola. Ale tak naprawdę nie ma istnienia zmiennej członka b, c. Ale dlaczego ???. OK, żeby nie zobaczyć. Tutaj b, c są zmiennymi instancji, ponieważ zmienna instancji pobiera pamięć w momencie tworzenia obiektu. Więc tutaj b, c nie dostają jeszcze żadnej pamięci. Dlatego nie ma b, c. Więc istnieje tylko istnienie. W przypadku ClassLoader ma tylko jedną informację o. ClassLoader jeszcze nie rozpoznaje b, c, ponieważ obiekt nie został jeszcze utworzony.

Zobaczmy inny przykład: Przykład 2:

class StaticTest {

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


      public static void main(String []cmd) {

             display();       
      }

}

Teraz, jeśli spróbujemy skompilować ten kompilator kodu, da błąd CE. CE: metody static-display display () nie można odwoływać się w kontekście statycznym.

Teraz dla ClassLoadera wygląda to tak:

class StaticTest {

      public static void main(String []cmd) {

             display();       
      }

}

W przykładzie 2 błąd CE wynika z tego, że wywołujemy metodę niestatyczną z kontekstu statycznego. Dlatego ClassLoader nie może rozpoznać metody display () w czasie kompilacji, więc wystąpił błąd czasu kompilacji.


Prawdopodobnie przesłałeś swoją odpowiedź przez przypadek, zanim udało Ci się ją ukończyć? Edytuj go i dodaj brakującą treść, dzięki!
plamut

1

Przed wywołaniem metody instancji lub zmiennej instancji Potrzebny jest obiekt (Instancja). Gdy zmienna instancji jest wywoływana ze statycznego kompilatora metod, nie wiadomo, do którego obiektu należy ta zmienna. Ponieważ metody statyczne nie mają obiektu (zawsze tylko jedna kopia). Kiedy wywołujesz zmienną instancji lub metody instancji z metody instancji, odwołuje się ona dothis obiektu. Oznacza to, że zmienna należy do dowolnego utworzonego obiektu, a każdy obiekt ma własną kopię metod i zmiennych instancji.

Zmienne statyczne są oznaczone jako, statica zmienne instancji nie mają określonego słowa kluczowego.


0

Jest to trochę trudne do wyjaśnienia na temat statycznego słowa kluczowego dla wszystkich początkujących.
Dowiesz się o tym wyraźnie, pracując więcej z klasami i przedmiotami.

| * | Statyczne: Przedmioty statyczne można wywoływać za pomocą Nazwy klasy
Jeśli zaobserwujesz w kodach, niektóre funkcje są wywoływane bezpośrednio za pomocą nazw klas, takich jak

NamCls.NamFnc();

System.out.println();

Wynika to z faktu, że NamFnc i println zostaną zadeklarowane przy użyciu słowa kluczowego static przed nimi.

| * | Niestatyczne: Przedmioty
niestatyczne można wywoływać za pomocą zmiennej klasy Jeśli nie jest statyczna, potrzebujesz zmiennej klasy,
umieść kropkę za zmienną klasy, a
następnie wywołaj funkcję.

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


Poniższy kod wyjaśnia dokładnie

| * | Funkcja statyczna i niestatyczna w klasie:

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


| * | Klasa statyczna i niestatyczna wewnątrz klasy:

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);
        }
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.