Cosa fa la parola chiave "statica" in una classe?


444

Per essere precisi, stavo provando questo codice:

package hello;

public class Hello {

    Clock clock = new Clock();

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

Ma ha dato l'errore

Impossibile accedere al campo non statico nel metodo statico principale

Quindi ho cambiato la dichiarazione di clockquesto:

static Clock clock = new Clock();

E ha funzionato. Cosa significa mettere quella parola chiave prima della dichiarazione? Cosa farà esattamente e / o limiterà in termini di cosa si può fare a quell'oggetto?


Ricorda ancora una volta che esiste un'istanza di una statica per classe per CLASSLOADER.
Javamann,

Risposte:


634

static i membri appartengono alla classe anziché a un'istanza specifica.

Significa che esiste solo un'istanza di un staticcampo [1] anche se crei un milione di istanze della classe o non ne crei nessuna. Sarà condiviso da tutte le istanze.

Poiché staticanche i metodi non appartengono a un'istanza specifica, non possono fare riferimento ai membri dell'istanza. Nell'esempio fornito, mainnon sa a quale istanza della Helloclasse (e quindi a quale istanza della Clockclasse) dovrebbe fare riferimento. statici membri possono fare riferimento solo ai staticmembri. I membri dell'istanza possono ovviamente accedere ai staticmembri.

Nota a margine: ovviamente, i staticmembri possono accedere ai membri dell'istanza tramite un riferimento a un oggetto .

Esempio:

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]: a seconda delle caratteristiche di runtime, può essere uno per ClassLoader o AppDomain o thread, ma non è questo il punto.


5
In .NET, puoi anche modificare questo comportamento usando l'attributo [ThreadStatic] - che rende il locale statico per thread particolari.
TheSoftwareJedi

4
So che questo è un vecchio post, ma per i principianti come me questo può essere utile. stackoverflow.com/questions/7026507/...
user3526905

Non saresti in grado di accedere a instance.instanceField poiché è una var privata? O è valido perché hai istanziato l'oggetto all'interno della sua stessa classe? Mi sembra un incubo ricorsivo, ma io sono un principiante di Java.
Matt Corby,

Se al membro statico di una classe viene fatto riferimento da 2 thread diversi, quante sono le istanze di quel membro statico? Mi sento come se fosse 2, ma se si desidera la stessa istanza tra i thread, è necessario utilizzare la parola chiave volatile. È corretto?
Dan

..e il valore viene conservato se non ci sono istanze della classe rimanenti?
mckenzm,

130

Significa che in Hello esiste solo un'istanza di "clock", non una per ogni istanza separata della classe "Hello", o più, significa che ci sarà un riferimento "clock" comunemente condiviso tra tutte le istanze di la classe "Ciao".

Quindi, se dovessi fare un "nuovo Hello" in un punto qualsiasi del tuo codice: A- nel primo scenario (prima della modifica, senza usare "statico"), si creerebbe un nuovo orologio ogni volta che viene chiamato un "nuovo Hello", ma B- nel secondo scenario (dopo la modifica, usando "statico"), ogni istanza "new Hello" condividerebbe e userebbe lo stesso riferimento iniziale e "clock" creato per primo.

A meno che tu non abbia bisogno di "orologio" da qualche parte al di fuori di main, questo funzionerebbe altrettanto bene:

package hello;
public class Hello
{
    public static void main(String args[])
    {
      Clock clock=new Clock();
      clock.sayTime();    
    }
}

Questo è il modo più normale di farlo. La main()routine dovrebbe essere autonoma.
Jason S,

1
Nel secondo caso creerebbe una nuova istanza di Clock ogni volta che viene chiamato il metodo principale, giusto?
Fai clic su Aggiorna

2
Nel secondo caso, clock statico, lo creerebbe una sola volta. Nel mio esempio, dove clock è all'interno del main, quindi sì, lo creerebbe nuovo ogni volta che viene chiamato main. Ma normalmente main viene chiamato solo una volta all'avvio del programma, e quando esce, tutto è libero.
Paul Tomblin,

Non riesco a capire come è possibile creare un nuovo orologio nel metodo principale? come dici tu lo creerebbe nuovo ogni volta che viene chiamato main, ma c'è solo un metodo principale. come quel metodo principale può fare riferimento a diverse istanze di clock? È un po 'difficile capire come sia possibile creare una nuova istanza di clock nel main e usare il suo metodo sayTime (), ma non è possibile estrarre l'istanza dal main e usare sayTime (). come è tutto gratuito quando main viene chiamato una volta? @PaulTomblin
ShakibaZar,

@ user5621266 Ho usato il mainmetodo solo perché l'OP ha fatto. Se invece fosse un metodo pubblico chiamato da altrove e la classe Hello fosse istanziata più di una volta, allora potrebbe creare un'istanza Clock per ogni istanza Hello, a meno che non clockfosse statica.
Paul Tomblin,

97

La staticparola chiave indica che qualcosa (un campo, un metodo o una classe nidificata) è correlato al tipo piuttosto che a qualsiasi istanza particolare del tipo. Quindi, ad esempio, si chiama Math.sin(...)senza alcuna istanza della Mathclasse e in effetti non è possibile creare un'istanza della Mathclasse.

Per ulteriori informazioni, consultare la parte pertinente del tutorial Java di Oracle .


Nota a margine

Java purtroppo consente di accedere a membri statici come se fossero membri di istanza, ad es

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

Questo fa sembrare che sleepsia un metodo di istanza, ma in realtà è un metodo statico - fa sempre dormire il thread corrente. È buona prassi chiarire questo nel codice chiamante:

// Clearer
Thread.sleep(5000);

1
Un altro esempio: System.out.println () sembra un metodo di classe, ma in realtà è un metodo di istanza. Poiché out è un'istanza PrintStream nella classe System.
Jiahui Zhang,

@LeslieCheung: No, non mi sembra un metodo di classe, come System.outnon mi piace un nome di tipo per me.
Jon Skeet,

42

La staticparola chiave in Java significa che la variabile o la funzione è condivisa tra tutte le istanze di quella classe in quanto appartiene al tipo , non gli oggetti reali stessi.

Quindi se hai una variabile: private static int i = 0;e la incrementi ( i++) in un'istanza, la modifica si rifletterà in tutte le istanze.isarà ora 1 in tutti i casi.

I metodi statici possono essere utilizzati senza istanziare un oggetto.


4
"Condivisa tra tutte le istanze" dà l'impressione sbagliata, IMO - si suggerisce che si fa necessità di avere un'istanza dell'oggetto.
Jon Skeet,

1
(Mentre in realtà non non hanno bisogno di essere eventuali istanze, perché il campo statico ecc appartiene al tipo .)
Jon Skeet

@Jon Skeet static appartiene al tipo, non all'oggetto? Puoi dirci più in dettaglio? Digita come tipo di dati: int, double, ...?
Truongnm,

@truongnm: digitare come nella classe che dichiara la variabile / metodo.
Jon Skeet,

26

Utilizzo di base dei membri statici ...

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
}

È così che puoi avere valori condivisi in tutti i membri della classe senza inviare l'istanza della classe Hello a un'altra classe. E con statico non è necessario creare un'istanza di classe.

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

Puoi semplicemente chiamare valori o metodi statici per nome della classe:

Hello.staticValue = "abc";

22

Statico significa che non è necessario creare un'istanza della classe per utilizzare i metodi o le variabili associati alla classe. Nel tuo esempio, puoi chiamare:

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

direttamente, invece di:

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

Dall'interno di un metodo statico (che appartiene a una classe) non è possibile accedere a membri che non sono statici, poiché i loro valori dipendono dall'istanza della classe. Un oggetto Clock non statico, che è un membro di istanza, avrebbe un valore / riferimento diverso per ogni istanza della classe Hello e pertanto non è possibile accedervi dalla parte statica della classe.


Grande spiegazione per il contesto statico :)
Abdel-Raouf,

20

Statico in Java:

Statico è un modificatore di non accesso. La parola chiave statica appartiene alla classe rispetto all'istanza della classe. può essere utilizzato per collegare una variabile o un metodo a una classe.

La parola chiave statica PU CAN essere utilizzata con:

Metodo

Variabile

Classe nidificata in un'altra classe

Blocco di inizializzazione

NON può essere utilizzato con:

Classe (non nidificata)

Costruttore

interfacce

Metodo Classe interna locale (differenza quindi classe nidificata)

Metodi della classe interna

Variabili di istanza

Variabili locali

Esempio:

Immagina il seguente esempio che ha una variabile di istanza denominata count che è incrementata nel costruttore:

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

    }
}

Produzione:

1 1 1

Poiché la variabile di istanza ottiene la memoria al momento della creazione dell'oggetto, ogni oggetto avrà la copia della variabile di istanza, se incrementata non si rifletterà su altri oggetti.

Ora se cambiamo il conteggio delle variabili di istanza in uno statico, il programma produrrà un output diverso:

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

    }
}

Produzione:

1 2 3

In questo caso la variabile statica otterrà la memoria una sola volta, se un oggetto modifica il valore della variabile statica, manterrà il suo valore.

Statico con finale:

La variabile globale dichiarata come definitiva e statica rimane invariata per l'intera esecuzione. Perché, i membri statici vengono archiviati nella memoria della classe e vengono caricati una sola volta nell'intera esecuzione. Sono comuni a tutti gli oggetti della classe. Se si dichiarano le variabili statiche come finali, nessuno degli oggetti non può modificarne il valore in quanto è definitivo. Pertanto, le variabili dichiarate come finali e statiche vengono talvolta chiamate Costanti. Tutti i campi delle interfacce sono indicati come costanti, perché sono finali e statici per impostazione predefinita.

inserisci qui la descrizione dell'immagine

Risorsa immagine: statico finale


15

Per aggiungere risposte esistenti, fammi provare con un'immagine:

Un tasso di interesse del 2% viene applicato a TUTTI i conti di risparmio. Quindi è statico .

Un equilibrio deve essere individuale , quindi è non è statica.

inserisci qui la descrizione dell'immagine


13

Questa discussione ha finora ignorato le considerazioni sul classloader. A rigor di termini, i campi statici Java sono condivisi tra tutte le istanze di una classe per un determinato programma di caricamento classi .


1
Questo è stato menzionato da Apocalisp nei commenti sulla risposta di Merhdad.
Zach Langley,

1
Buon punto. Molte persone non lo sanno, ma una volta che inizi a fare casini con i caricatori di classi, diventa molto importante.
sleske,

2
Questo è tutto vero ma non risponde alla domanda. Avrebbe dovuto essere pubblicato come commento.
Marchese di Lorne,

7

Un campo può essere assegnato alla classe o a un'istanza di una classe. Per impostazione predefinita, i campi sono variabili di istanza. Usando staticil campo diventa una variabile di classe, quindi ne esiste una sola clock. Se apporti modifiche in un unico posto, è visibile ovunque. Le varianti delle istanze vengono modificate indipendentemente l'una dall'altra.


6

La parola chiave staticviene utilizzata per indicare un campo o un metodo come appartenenti alla classe stessa e non all'istanza. Usando il codice, se l'oggetto Clockè statico, tutte le istanze della Helloclasse condivideranno questo Clockmembro di dati (campo) in comune. Se lo rendi non statico, ogni singola istanza di Hellopuò avere un unicoClock campo .

Il problema è che hai aggiunto un metodo principale alla tua classe in Hellomodo da poter eseguire il codice. Il problema qui è che il metodo principale è statico e come tale non può fare riferimento a campi o metodi non statici al suo interno. Puoi risolverlo in due modi:

  1. Rendi Hellostatici tutti i campi e i metodi della classe in modo che possano essere citati all'interno del principale metodo . Questa non è davvero una buona cosa da fare (o la ragione sbagliata per rendere statico un campo e / o un metodo)
  2. Crea un'istanza della tua Helloclasse all'interno del metodo principale e accedi a tutti i suoi campi e metodi nel modo in cui erano previsti in primo luogo.

Per te, questo significa la seguente modifica al tuo codice:

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

6

In Java, la staticparola chiave può essere semplicemente considerata indicando quanto segue:

"senza riguardo o relazione con qualsiasi istanza particolare"

Se la pensi staticin questo modo, diventa più facile comprenderne l'uso nei vari contesti in cui si incontra:

  • Un staticcampo è un campo che appartiene alla classe piuttosto che a qualsiasi istanza particolare

  • Un staticmetodo è un metodo che non ha alcuna nozione di this; è definito sulla classe e non conosce alcuna particolare istanza di quella classe a meno che non venga passato un riferimento ad essa

  • Una staticclasse membro è una classe nidificata senza alcuna nozione o conoscenza di un'istanza della sua classe acclusa (a meno che non venga passato ad essa un riferimento a un'istanza della classe acclusa)


5

Statico rende il membro di clock un membro di classe anziché un membro di istanza. Senza la parola chiave statica dovresti creare un'istanza della classe Hello (che ha una variabile membro clock) - ad es

Hello hello = new Hello();
hello.clock.sayTime();

5

i metodi statici non utilizzano alcuna variabile di istanza della classe in cui sono definiti. In questa pagina è possibile trovare un'ottima spiegazione della differenza


5

Ho sviluppato una predilezione per i metodi statici (solo, se possibile) nelle classi "helper".

La classe chiamante non deve creare un'altra variabile membro (istanza) della classe helper. Basta chiamare i metodi della classe helper. Anche la classe helper è stata migliorata perché non è più necessario un costruttore e non sono necessarie variabili membro (istanza).

Probabilmente ci sono altri vantaggi.


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

3

Può anche pensare ai membri statici che non hanno un "questo" puntatore. Sono condivisi tra tutti i casi.


3

Comprensione dei concetti statici

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 */

    }
}

Seconda classe

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

    public void printUddhav() {
        System.out.println("Uddhav");
    }
}

2

main() è un metodo statico che ha due restrizioni fondamentali:

  1. Il metodo statico non può utilizzare un membro di dati non statico o chiamare direttamente il metodo non statico.
  2. this()e super()non può essere utilizzato in un contesto statico.

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

Output: errore tempo di compilazione


1

Le variabili statiche sono accessibili solo nei metodi statici, quindi quando dichiariamo le variabili statiche quei metodi getter e setter saranno metodi statici

i metodi statici sono un livello di classe a cui possiamo accedere usando il nome della classe

Di seguito è riportato un esempio per Getter e setter di variabili statiche:

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

}

1

Una domanda è stato chiesto qui sulla scelta della parola 'statica' per questo concetto. Era collegato a questa domanda, ma non credo che l'etimologia sia stata affrontata chiaramente. Così...


È dovuto al riutilizzo delle parole chiave, a partire da C.

Considera le dichiarazioni di dati in C (all'interno di un corpo di funzione):

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

La variabile foo viene creata nello stack quando la funzione viene inserita (e distrutta al termine della funzione). Al contrario, la barra è sempre lì, quindi è "statica" nel senso dell'inglese comune - non va da nessuna parte.

Java e linguaggi simili hanno lo stesso concetto per i dati. I dati possono essere allocati per istanza della classe (per oggetto) o una volta per l'intera classe. Poiché Java mira ad avere una sintassi familiare per i programmatori C / C ++, la parola chiave "statica" è appropriata qui.

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

Infine, arriviamo ai metodi.

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

Esiste, concettualmente parlando, un'istanza di foo () per ogni istanza della classe C. C'è solo un'istanza di bar () per l'intera classe C. Questo è parallelo al caso che abbiamo discusso per i dati, e quindi usando 'static "è di nuovo una scelta sensata, soprattutto se non desideri aggiungere parole chiave più riservate alla tua lingua.

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.