Co robi słowo kluczowe „static” w klasie?

444

Aby być konkretnym, próbowałem tego kodu:

package hello;

public class Hello {

    Clock clock = new Clock();

    public static void main(String args[]) {
        clock.sayTime();
    }
}

Ale dał błąd

Nie można uzyskać dostępu do pola niestatycznego w metodzie statycznej main

Zmieniłem więc deklarację clockna:

static Clock clock = new Clock();

I zadziałało. Co oznacza umieszczenie tego słowa kluczowego przed deklaracją? Co dokładnie zrobi i / lub ograniczy w zakresie tego, co można zrobić z tym obiektem?

Kliknij opcję Upvote
źródło
Po raz kolejny pamiętaj, że na klasę przypada jeden przypadek statyczny na klasę CLASSLOADER.
Javamann

Odpowiedzi:

633

static członkowie należą do klasy zamiast określonej instancji.

Oznacza to, że istnieje tylko jedna instancja staticpola [1], nawet jeśli utworzysz milion instancji klasy lub nie utworzysz żadnej. Zostanie udostępniony przez wszystkie instancje.

Ponieważ staticmetody również nie należą do określonej instancji, nie mogą odnosić się do członków instancji. W podanym przykładzie mainnie wie, do której instancji Helloklasy (a zatem i do której instancji Clockklasy) powinien się odnosić. staticczłonkowie mogą odnosić się tylko do staticczłonków. Członkowie instancji mogą oczywiście uzyskiwać dostęp do staticczłonków.

Uwaga dodatkowa: Oczywiście staticczłonkowie mogą uzyskać dostęp do elementów instancji poprzez odwołanie do obiektu .

Przykład:

public class Example {
    private static boolean staticField;
    private boolean instanceField;
    public static void main(String[] args) {
        // a static method can access static fields
        staticField = true;

        // a static method can access instance fields through an object reference
        Example instance = new Example();
        instance.instanceField = true;
    }

[1]: W zależności od właściwości środowiska wykonawczego może to być jeden na ClassLoader, AppDomain lub wątek, ale to nie ma sensu.

Mehrdad Afshari
źródło
5
W .NET można również zmodyfikować to zachowanie za pomocą atrybutu [ThreadStatic] - co powoduje, że statyczny jest lokalny dla poszczególnych wątków.
TheSoftwareJedi
4
Wiem, że to stary post, ale dla początkujących takich jak ja może to być pomocne. stackoverflow.com/questions/7026507/…
user3526905
Czy nie byłbyś w stanie uzyskać dostępu do instance.instanceField, ponieważ jest to prywatny var? A może jest prawidłowy, ponieważ utworzyłeś obiekt w jego własnej klasie? Brzmi jak rekurencyjny koszmar, ale jestem nowicjuszem w Javie.
Matt Corby,
Jeśli do elementu statycznego klasy odwołują się 2 różne wątki, to ile wystąpień ma ten element statyczny? Wydaje mi się, że to 2, ale jeśli chcesz mieć tę samą instancję w wątkach, musisz użyć niestabilnego słowa kluczowego. Czy to jest poprawne?
Dan.
... i czy wartość zostaje zachowana, jeśli nie pozostały żadne instancje klasy?
mckenzm,
130

Oznacza to, że w Hello jest tylko jedna instancja „zegara”, a nie jedna na każdą oddzielną instancję klasy „Hello”, a co więcej, oznacza to, że pomiędzy wszystkimi instancjami będzie jedno wspólne odwołanie do „zegara”. klasa „Cześć”.

Więc jeśli miałbyś zrobić „nowe powitanie” w dowolnym miejscu kodu: A- w pierwszym scenariuszu (przed zmianą, bez użycia „statycznego”), tworzyłby nowy zegar za każdym razem, gdy wywoływane jest „nowe powitanie”, ale B - w drugim scenariuszu (po zmianie, używając „statycznego”), każda instancja „nowego Hello” nadal będzie współdzielić i używać początkowej i tej samej referencji „clock”, która została utworzona jako pierwsza.

O ile nie potrzebujesz „zegara” poza głównym obszarem, działałoby to równie dobrze:

package hello;
public class Hello
{
    public static void main(String args[])
    {
      Clock clock=new Clock();
      clock.sayTime();    
    }
}
Paul Tomblin
źródło
Jest to bardziej typowy sposób na zrobienie tego. Procedura main()powinna być samodzielna.
Jason S
1
W drugim przypadku tworzyłoby nowe wystąpienie Zegara za każdym razem, gdy wywoływana jest główna metoda, prawda?
Kliknij Upvote
2
W drugim przypadku, zegar statyczny, utworzyłby go tylko raz. W moim przykładzie, gdzie zegar znajduje się w głównym, wtedy tak, tworzyłby go nowy za każdym razem, gdy główny jest wywoływany. Ale zwykle main jest wywoływany tylko raz podczas uruchamiania programu, a kiedy kończy działanie, wszystko jest bezpłatne.
Paul Tomblin
Nie mogę zrozumieć, jak można zrobić nowy zegar w metodzie głównej? jak mówisz, tworzyłby go nowy za każdym razem, gdy wywoływana jest funkcja main, ale istnieje tylko jedna główna metoda. jak ta główna metoda może odnosić się do różnych instancji zegara? Trochę trudno jest zrozumieć, w jaki sposób można utworzyć nową instancję zegara w main i użyć jej metody sayTime (), ale nie jest możliwe wykonanie instancji poza main i użycie sayTime (). jak wszystko jest darmowe, gdy main jest wywoływana raz? @PaulTomblin
ShakibaZar
@ user5621266 Użyłem tej mainmetody tylko dlatego, że OP. Jeśli zamiast tego była to metoda publiczna, która została wywołana z innego miejsca, a klasa Hello została utworzona instancja więcej niż raz, wówczas mogłaby utworzyć instancję Clock dla każdej instancji Hello, chyba że clockjest statyczna.
Paul Tomblin
97

Słowo statickluczowe oznacza, że ​​coś (pole, metoda lub klasa zagnieżdżona) jest powiązane z typem, a nie z konkretną instancją typu. Na przykład, wywołuje się Math.sin(...)bez żadnej instancji Mathklasy i rzeczywiście nie można utworzyć instancji Mathklasy.

Aby uzyskać więcej informacji, zobacz odpowiedni fragment samouczka Java firmy Oracle .


Dygresja

Java niestety pozwala na dostęp do elementów statycznych tak, jakby były członkami instancji, np

// Bad code!
Thread.currentThread().sleep(5000);
someOtherThread.sleep(5000);

To sprawia, że wygląda na sleepmetodę instancji, ale w rzeczywistości jest to metoda statyczna - zawsze uśpia bieżący wątek. Lepiej jest to wyjaśnić w kodzie wywołującym:

// Clearer
Thread.sleep(5000);
Jon Skeet
źródło
1
Kolejny przykład: System.out.println () wygląda jak metoda klasy, ale w rzeczywistości jest to metoda instancji. Ponieważ out jest instancją PrintStream w klasie System.
Jiahui Zhang
@LeslieCheung: Nie, nie wygląda mi to na metodę klasową, ponieważ System.outnie podoba mi się nazwa typu.
Jon Skeet
42

Słowo statickluczowe w Javie oznacza, że ​​zmienna lub funkcja jest wspólna dla wszystkich instancji tej klasy, ponieważ należy do typu , a nie do samych obiektów.

Więc jeśli masz zmienną: private static int i = 0;i zwiększasz ją ( i++) w jednym wystąpieniu, zmiana zostanie odzwierciedlona we wszystkich wystąpieniach. ibędzie teraz wynosić 1 we wszystkich przypadkach.

Można stosować metody statyczne bez tworzenia obiektu.

geowa4
źródło
4
„Wspólna między wszystkie instancje” daje mylne wrażenie, IMO - to sugeruje zrobić trzeba mieć wystąpienie obiektu.
Jon Skeet
1
(Podczas gdy naprawdę nie muszą być żadnych instancji, ponieważ pole statyczne itp. Należy do tego typu .)
Jon Skeet
@Jon Skeet static należy do typu, a nie do obiektu? Czy możesz powiedzieć więcej szczegółów? Wpisz typ danych: int, double, ...?
truongnm
@truongnm: Wpisz jak w klasie, która deklaruje zmienną / metodę.
Jon Skeet
26

Podstawowe użycie elementów statycznych ...

public class Hello
{
    // value / method
    public static String staticValue;
    public String nonStaticValue;
}

class A
{
    Hello hello = new Hello();
    hello.staticValue = "abc";
    hello.nonStaticValue = "xyz";
}

class B
{
    Hello hello2 = new Hello(); // here staticValue = "abc"
    hello2.staticValue; // will have value of "abc"
    hello2.nonStaticValue; // will have value of null
}

W ten sposób można udostępniać wartości wszystkim członkom klasy bez wysyłania instancji klasy Witaj w innej klasie. I odrobinę statyczne, nie musisz tworzyć instancji klasy.

Hello hello = new Hello();
hello.staticValue = "abc";

Możesz po prostu wywoływać wartości statyczne lub metody według nazwy klasy:

Hello.staticValue = "abc";
Vasil Valchev
źródło
22

Statyczny oznacza, że ​​nie trzeba tworzyć instancji klasy, aby korzystać z metod lub zmiennych powiązanych z klasą. W twoim przykładzie możesz zadzwonić:

Hello.main(new String[]()) //main(...) is declared as a static function in the Hello class

bezpośrednio, zamiast:

Hello h = new Hello();
h.main(new String[]()); //main(...) is a non-static function linked with the "h" variable

Z wnętrza metody statycznej (która należy do klasy) nie można uzyskać dostępu do żadnych elementów, które nie są statyczne, ponieważ ich wartości zależą od instancji klasy. Niestatyczny obiekt Clock, który jest członkiem instancji, miałby inną wartość / referencję dla każdej instancji klasy Hello, a zatem nie można uzyskać do niego dostępu ze statycznej części klasy.

Elie
źródło
Świetne wyjaśnienie dla kontekstu statycznego :)
Abdel-Raouf
20

Statyczne w Javie:

Statyczny jest modyfikatorem braku dostępu. Statyczne słowo kluczowe należy do klasy niż instancja klasy. może być użyty do dołączenia zmiennej lub metody do klasy.

Statyczne słowo kluczowe MOŻE być używane z:

metoda

Zmienna

Klasa zagnieżdżona w innej klasie

Blok inicjalizacji

NIE MOŻNA używać z:

Klasa (nie zagnieżdżona)

Konstruktor

Interfejsy

Metoda lokalna klasa wewnętrzna (różnica a klasa zagnieżdżona)

Metody klasy wewnętrznej

Zmienne instancji

Zmienne lokalne

Przykład:

Wyobraź sobie następujący przykład, który ma zmienną instancji o nazwie count, która jest zwiększana w konstruktorze:

package pkg;

class StaticExample {
    int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

Wynik:

1 1 1

Ponieważ zmienna instancji otrzymuje pamięć w momencie tworzenia obiektu, każdy obiekt będzie miał kopię zmiennej instancji, jeśli zostanie zwiększona, nie będzie odzwierciedlała innych obiektów.

Teraz, jeśli zmienimy liczbę zmiennych instancji na statyczną, wówczas program wygeneruje inne dane wyjściowe:

package pkg;

class StaticExample {
    static int count = 0;// will get memory when instance is created

    StaticExample() {
        count++;
        System.out.println(count);
    }

    public static void main(String args[]) {

        StaticExample c1 = new StaticExample();
        StaticExample c2 = new StaticExample();
        StaticExample c3 = new StaticExample();

    }
}

Wynik:

1 2 3

W takim przypadku zmienna statyczna pobierze pamięć tylko raz, jeśli dowolny obiekt zmieni wartość zmiennej statycznej, zachowa swoją wartość.

Statyczne z ostatecznym:

Zmienna globalna zadeklarowana jako ostateczna i statyczna pozostaje niezmieniona dla całego wykonania. Ponieważ elementy statyczne są przechowywane w pamięci klas i są ładowane tylko raz podczas całego wykonania. Są wspólne dla wszystkich obiektów klasy. Jeśli zadeklarujesz zmienne statyczne jako końcowe, żaden z obiektów nie będzie mógł zmienić ich wartości, ponieważ jest ona ostateczna. Dlatego zmienne zadeklarowane jako ostateczne i statyczne są czasami nazywane stałymi. Wszystkie pola interfejsów są nazywane stałymi, ponieważ domyślnie są one ostateczne i statyczne.

wprowadź opis zdjęcia tutaj

Zasób obrazu: Final Static

Affy
źródło
15

Aby dodać do istniejących odpowiedzi, pozwól mi spróbować ze zdjęciem:

Do WSZYSTKICH kont oszczędnościowych stosowana jest stopa procentowa w wysokości 2%. Dlatego jest statyczny .

Równowaga powinna być indywidualna , więc to nie statyczne.

wprowadź opis zdjęcia tutaj

Andrejs
źródło
13

W tej dyskusji dotychczas ignorowano uwagi dotyczące modułu ładującego klasy. Ściśle mówiąc, pola statyczne Java są wspólne dla wszystkich instancji klasy dla danego modułu ładującego klasy .

Julien Chastang
źródło
1
Zostało to wspomniane przez Apocalisp w komentarzach do odpowiedzi Merhdada.
Zach Langley,
1
Słuszna uwaga. Wiele osób nie wie o tym, ale kiedy zaczniesz bawić się modułami ładującymi klasy, staje się to bardzo ważne.
sleske,
2
To wszystko prawda, ale nie odpowiada na pytanie. Powinien zostać opublikowany jako komentarz.
Markiz Lorne
7

Pole może być przypisane do klasy lub instancji klasy. Domyślnie pola są zmiennymi instancji. Użycie staticpola staje się zmienną klasową, a więc istnieje jedna i tylko jedna clock. Jeśli dokonasz zmian w jednym miejscu, będzie to widoczne wszędzie. Zmienne instancji są zmieniane niezależnie od siebie.

sblundy
źródło
6

Słowo kluczowe staticsłuży do oznaczenia pola lub metody jako należących do samej klasy, a nie do instancji. Używając kodu, jeśli obiekt Clockjest statyczny, wszystkie instancje Helloklasy będą współużytkować ten Clockelement danych (pole). Jeśli uczynisz go niestatycznym, każda pojedyncza instancja Hellomoże mieć unikalnyClock pole.

Problem polega na tym, że dodałeś główną metodę do swojej klasy Hello, abyś mógł uruchomić kod. Problem polega na tym, że główna metoda jest statyczna i jako taka nie może odnosić się do niestatystycznych pól lub metod w niej zawartych. Możesz rozwiązać ten problem na dwa sposoby:

  1. Ustaw wszystkie pola i metody Helloklasy w sposób statyczny, aby można było do nich odwoływać się w metodzie głównej . To naprawdę nie jest dobra rzecz (lub niewłaściwy powód, dla którego pole i / lub metoda stają się statyczne)
  2. Utwórz instancję swojej Helloklasy w głównej metodzie i uzyskaj dostęp do wszystkich jej pól i metod tak, jak powinny.

Dla Ciebie oznacza to następującą zmianę w kodzie:

package hello;

public class Hello {

    private Clock clock = new Clock();

    public Clock getClock() {
        return clock;
    }

    public static void main(String args[]) {
        Hello hello = new Hello();
        hello.getClock().sayTime();
    }
}
hfontanez
źródło
6

W Javie staticsłowo kluczowe można po prostu uznać za wskazujące:

„bez względu na związek z jakimkolwiek konkretnym przypadkiem”

Jeśli myślisz o statictym w ten sposób, łatwiej jest zrozumieć jego zastosowanie w różnych kontekstach, w których się pojawia:

  • staticPole jest dziedziną, która należy do klasy, a nie do konkretnej instancji

  • staticMetoda jest metodą, która nie ma pojęcia this; jest zdefiniowany w klasie i nie wie o żadnym konkretnym wystąpieniu tej klasy, chyba że zostanie do niej przekazane odwołanie

  • staticKlasy element jest zagnieżdżony klasy bez pojęciem lub wiedzy na przykład tej klasy okalającego (chyba, że odniesienie do otaczającej przykład klasy jest przekazywane do niego)

Scott
źródło
5

Statyczny powoduje, że element zegarowy jest członkiem klasy zamiast członkiem instancji. Bez statycznego słowa kluczowego należy utworzyć instancję klasy Hello (która ma zmienną składową zegara) - np

Hello hello = new Hello();
hello.clock.sayTime();
Stephen Doyle
źródło
5

metody statyczne nie używają żadnych zmiennych instancji klasy, w której są zdefiniowane. Bardzo dobre wyjaśnienie różnicy można znaleźć na tej stronie

Marc Nowakowski
źródło
5

Polubiłem metody statyczne (tylko, jeśli to możliwe) w klasach „pomocników”.

Klasa wywołująca nie musi tworzyć innej zmiennej członka (instancji) klasy pomocniczej. Po prostu wywołujesz metody klasy pomocniczej. Ulepszono także klasę pomocnika, ponieważ nie potrzebujesz już konstruktora i nie potrzebujesz zmiennych członka (instancji).

Są prawdopodobnie inne zalety.

javaguy
źródło
4
//Here is an example 

public class StaticClass 
{
    static int version;
    public void printVersion() {
         System.out.println(version);
    }
}

public class MainClass 
{
    public static void main(String args[]) {  
        StaticClass staticVar1 = new StaticClass();
        staticVar1.version = 10;
        staticVar1.printVersion() // Output 10

        StaticClass staticVar2 = new StaticClass();
        staticVar2.printVersion() // Output 10
        staticVar2.version = 20;
        staticVar2.printVersion() // Output 20
        staticVar1.printVersion() // Output 20
    }
}
Mohammad Parvez
źródło
3

Może również myśleć o elementach statycznych, które nie mają wskaźnika „ten”. Są one wspólne dla wszystkich instancji.

kal
źródło
3

Zrozumienie pojęć statycznych

public class StaticPractise1 {
    public static void main(String[] args) {
        StaticPractise2 staticPractise2 = new StaticPractise2();
        staticPractise2.printUddhav(); //true
        StaticPractise2.printUddhav(); /* false, because printUddhav() is although inside StaticPractise2, but it is where exactly depends on PC program counter on runtime. */

        StaticPractise2.printUddhavsStatic1(); //true
        staticPractise2.printUddhavsStatic1(); /*false, because, when staticPractise2 is blueprinted, it tracks everything other than static  things and it organizes in its own heap. So, class static methods, object can't reference */

    }
}

Druga klasa

public class StaticPractise2 {
    public static void printUddhavsStatic1() {
        System.out.println("Uddhav");
    }

    public void printUddhav() {
        System.out.println("Uddhav");
    }
}
Uddhav Gautam
źródło
2

main() jest metodą statyczną, która ma dwa podstawowe ograniczenia:

  1. Metoda statyczna nie może używać niestatycznego elementu danych ani bezpośrednio wywoływać metody niestatycznej.
  2. this()i super()nie można go używać w kontekście statycznym.

    class A {  
        int a = 40; //non static
        public static void main(String args[]) {  
            System.out.println(a);  
        }  
    }

Dane wyjściowe: błąd czasu kompilacji

Bharthan
źródło
1

Zmienne statyczne Można uzyskać dostęp tylko w metodach statycznych, więc kiedy zadeklarujemy zmienne statyczne, te metody pobierające i ustawiające będą metodami statycznymi

metody statyczne to poziom klasy, do którego możemy uzyskać dostęp za pomocą nazwy klasy

Poniżej przedstawiono przykład dla zmiennych pobierających i ustawiających zmienne statyczne:

public class Static 
{

    private static String owner;
    private static int rent;
    private String car;
    public String getCar() {
        return car;
    }
    public void setCar(String car) {
        this.car = car;
    }
    public static int getRent() {
        return rent;
    }
    public static void setRent(int rent) {
        Static.rent = rent;
    }
    public static String getOwner() {
        return owner;
    }

    public static void setOwner(String owner) {
        Static.owner = owner;
    }

}
Bala Krishna
źródło
1

Zadano tutaj pytanie dotyczące wyboru słowa „statyczny” dla tej koncepcji. Zadano to pytanie w odpowiedzi na to pytanie, ale nie sądzę, aby etymologia została wyraźnie uwzględniona. Więc...


Jest to spowodowane ponownym użyciem słowa kluczowego, zaczynając od C.

Rozważ deklaracje danych w C (w ciele funkcji):

    void f() {
        int foo = 1;
        static int bar = 2;
         :
    }

Zmienna foo jest tworzona na stosie, gdy funkcja jest wprowadzana (i niszczona, gdy funkcja się kończy). Natomiast pasek jest zawsze obecny, więc jest „statyczny” w znaczeniu zwykłego angielskiego - nigdzie się nie wybiera.

Java i podobne języki mają tę samą koncepcję danych. Dane można albo przydzielić na instancję klasy (na obiekt), albo raz dla całej klasy. Ponieważ Java chce mieć znaną składnię dla programistów C / C ++, właściwe jest tutaj słowo kluczowe „static”.

    class C {
        int foo = 1;
        static int bar = 2;
         :
    }

Wreszcie dochodzimy do metod.

    class C {
        int foo() { ... }
        static int bar() { ... }
         :
    }

Istnieje, pod względem koncepcyjnym, instancja foo () dla każdej instancji klasy C. Istnieje tylko jedna instancja bar () dla całej klasy C. Jest to równoległe z przypadkiem, który omawialiśmy dla danych, i dlatego używa „static „jest znowu rozsądnym wyborem, zwłaszcza jeśli nie chcesz dodawać do swojego języka bardziej zastrzeżonych słów kluczowych.

użytkownik13068046
źródło