Que fait le mot clé "statique" dans une classe?


444

Pour être précis, j'essayais ce code:

package hello;

public class Hello {

    Clock clock = new Clock();

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

Mais cela a donné l'erreur

Impossible d'accéder au champ non statique dans la méthode statique principale

J'ai donc changé la déclaration de clockceci:

static Clock clock = new Clock();

Et ça a marché. Que signifie mettre ce mot-clé avant la déclaration? Que va-t-il faire exactement et / ou restreindre en termes de ce qui peut être fait pour cet objet?


Rappelez-vous une fois de plus qu'il existe une instance statique par classe et par CLASSLOADER.
Javamann

Réponses:


633

static les membres appartiennent à la classe au lieu d'une instance spécifique.

Cela signifie qu'une seule instance d'un staticchamp existe [1] même si vous créez un million d'instances de la classe ou si vous n'en créez pas. Il sera partagé par toutes les instances.

Étant donné que les staticméthodes n'appartiennent pas non plus à une instance spécifique, elles ne peuvent pas faire référence aux membres de l'instance. Dans l'exemple donné, mainne sait pas à quelle instance de la Helloclasse (et donc à quelle instance de la Clockclasse) il doit se référer. staticles membres ne peuvent se référer qu'aux staticmembres. Les membres de l'instance peuvent, bien sûr, accéderstatic membres.

Note latérale: Bien sûr, les staticmembres peuvent accéder aux membres d'instance via une référence d'objet .

Exemple:

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]: Selon les caractéristiques d'exécution, il peut s'agir d'un par ClassLoader ou AppDomain ou thread, mais c'est à côté du point.


5
Dans .NET, vous pouvez également modifier ce comportement à l'aide de l'attribut [ThreadStatic] - qui rend le local statique à des threads particuliers.
TheSoftwareJedi

4
Je sais que c'est un ancien message, mais pour les débutants comme moi, cela peut être utile. stackoverflow.com/questions/7026507/…
user3526905

Ne seriez-vous pas incapable d'accéder à instance.instanceField puisqu'il s'agit d'une var privée? Ou est-ce valide parce que vous avez instancié l'objet dans sa propre classe? Cela ressemble à un cauchemar récursif pour moi, mais je suis un débutant Java.
Matt Corby

Si le membre statique d'une classe est référencé par 2 threads différents, alors combien d'instances y a-t-il de ce membre statique? J'ai l'impression que c'est 2 mais si vous voulez la même instance à travers les threads, alors le mot-clé volatile doit être utilisé. Est-ce exact?
Dan

..et la valeur est-elle préservée s'il ne reste aucune instance de la classe?
mckenzm

130

Cela signifie qu'il n'y a qu'une seule instance de "horloge" dans Hello, pas une pour chaque instance distincte de la classe "Hello", ou plus, cela signifie qu'il y aura une référence "d'horloge" communément partagée entre toutes les instances de la classe "Bonjour".

Donc, si vous deviez faire un "nouveau Bonjour" n'importe où dans votre code: A- dans le premier scénario (avant le changement, sans utiliser "statique"), cela ferait une nouvelle horloge chaque fois qu'un "nouveau Bonjour" est appelé, mais B- dans le deuxième scénario (après le changement, en utilisant "statique"), chaque "nouvelle Bonjour" instance partagerait et utiliserait la référence initiale et identique "d'horloge" créée en premier.

Sauf si vous aviez besoin d'une "horloge" quelque part en dehors du principal, cela fonctionnerait aussi bien:

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

C'est la façon la plus habituelle de procéder. La main()routine doit être autonome.
Jason S

1
Dans le deuxième cas, cela créerait une nouvelle instance de Clock à chaque fois que la méthode principale est appelée, non?
Cliquez sur Upvote

2
Dans le deuxième cas, horloge statique, il ne la créait qu'une seule fois. Dans mon exemple, où l'horloge est dans le principal, alors oui, cela le créerait à chaque fois que le principal est appelé. Mais normalement, main n'est appelé qu'une seule fois au démarrage du programme, et quand il se termine, tout est libre.
Paul Tomblin

Je n'arrive pas à savoir comment est-il possible de faire une nouvelle horloge dans la méthode principale? comme vous le dites, il le créerait à chaque appel principal, mais il n'y a qu'une seule méthode principale. comment cette méthode principale peut faire référence à différentes instances d'horloge? Il est un peu difficile de comprendre comment il est possible de créer une nouvelle instance d'horloge dans le principal et d'utiliser sa méthode sayTime (), mais il n'est pas possible de faire l'instance hors du principal et d'utiliser sayTime (). comment tout est-il gratuit lorsque le principal est appelé une fois? @PaulTomblin
ShakibaZar

@ user5621266 J'ai utilisé la mainméthode uniquement parce que l'OP l'a fait. Si, à la place, il s'agissait d'une méthode publique appelée ailleurs et que la classe Hello était instanciée plusieurs fois, elle pouvait créer une instance Clock pour chaque instance Hello, sauf si elle clockétait statique.
Paul Tomblin

97

Le staticmot-clé signifie que quelque chose (un champ, une méthode ou une classe imbriquée) est lié au type plutôt qu'à une instance particulière du type. Ainsi, par exemple, on appelle Math.sin(...)sans aucune instance de la Mathclasse, et en effet vous ne pouvez pas créer une instance de la Mathclasse.

Pour plus d'informations, consultez la partie pertinente du didacticiel Java d'Oracle .


Sidenote

Java vous permet malheureusement d'accéder aux membres statiques comme s'ils étaient des membres d'instance, par exemple

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

Cela donne l' impression que sleepc'est une méthode d'instance, mais c'est en fait une méthode statique - cela fait toujours dormir le thread actuel. Il est préférable de clarifier cela dans le code appelant:

// Clearer
Thread.sleep(5000);

1
Un autre exemple: System.out.println () ressemble à une méthode de classe, mais c'est en fait une méthode d'instance. Puisque out est une instance PrintStream de la classe System.
Jiahui Zhang

@LeslieCheung: Non, cela ne ressemble pas à une méthode de classe pour moi, pas plus qu'à System.outun nom de type.
Jon Skeet

42

Le staticmot clé en Java signifie que la variable ou la fonction est partagée entre toutes les instances de cette classe car elle appartient au type , pas les objets réels eux-mêmes.

Donc, si vous avez une variable: private static int i = 0;et que vous l'incrémentez ( i++) dans une instance, le changement sera reflété dans toutes les instances.isera désormais égal à 1 dans tous les cas.

Les méthodes statiques peuvent être utilisées sans instancier un objet.


4
« Partagé entre toutes les instances » donne l'impression erronée, l' OMI - il suggère que vous avez besoin d'avoir une instance de l'objet.
Jon Skeet

1
(Alors que vraiment il n'a pas besoin d'être des cas, car le champ statique etc appartient au genre .)
Jon Skeet

@Jon Skeet static appartient au type, pas à l'objet? Pouvez-vous nous en dire plus? Type comme type de données: int, double, ...?
truongnm

@truongnm: Tapez comme dans la classe qui déclare la variable / méthode.
Jon Skeet

26

Utilisation de base des membres statiques ...

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
}

C'est ainsi que vous pouvez partager des valeurs dans tous les membres de la classe sans envoyer l'instance de classe Hello à une autre classe. Et avec statique, vous n'avez pas besoin de créer d'instance de classe.

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

Vous pouvez simplement appeler des valeurs ou des méthodes statiques par nom de classe:

Hello.staticValue = "abc";

22

Statique signifie que vous n'avez pas besoin de créer une instance de la classe pour utiliser les méthodes ou variables associées à la classe. Dans votre exemple, vous pouvez appeler:

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

directement, au lieu de:

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

De l'intérieur d'une méthode statique (qui appartient à une classe), vous ne pouvez pas accéder aux membres qui ne sont pas statiques, car leurs valeurs dépendent de votre instanciation de la classe. Un objet Clock non statique, qui est un membre d'instance, aurait une valeur / référence différente pour chaque instance de votre classe Hello, et vous ne pouvez donc pas y accéder à partir de la partie statique de la classe.


Grande explication du contexte statique :)
Abdel-Raouf

20

Statique en Java:

Static est un modificateur sans accès. Le mot-clé statique appartient à la classe que l'instance de la classe. peut être utilisé pour attacher une variable ou une méthode à une classe.

Le mot-clé statique PEUT être utilisé avec:

Méthode

Variable

Classe imbriquée dans une autre classe

Bloc d'initialisation

NE PEUT PAS être utilisé avec:

Classe (non imbriquée)

Constructeur

Interfaces

Méthode classe interne locale (différence puis classe imbriquée)

Méthodes de classe interne

Variables d'instance

Variables locales

Exemple:

Imaginez l'exemple suivant qui a une variable d'instance nommée count qui est incrémentée dans le constructeur:

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

    }
}

Production:

1 1 1

Puisque la variable d'instance obtient la mémoire au moment de la création de l'objet, chaque objet aura la copie de la variable d'instance, si elle est incrémentée, elle ne se reflétera pas sur les autres objets.

Maintenant, si nous changeons le nombre de variables d'instance en nombre statique, le programme produira une sortie différente:

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

    }
}

Production:

1 2 3

Dans ce cas, la variable statique n'obtiendra la mémoire qu'une seule fois, si un objet modifie la valeur de la variable statique, il conservera sa valeur.

Statique avec finale:

La variable globale qui est déclarée finale et statique reste inchangée pour toute l'exécution. Parce que, les membres statiques sont stockés dans la mémoire de classe et ils ne sont chargés qu'une seule fois dans l'exécution entière. Ils sont communs à tous les objets de la classe. Si vous déclarez des variables statiques comme finales, aucun des objets ne peut changer leur valeur car elle est finale. Par conséquent, les variables déclarées comme finales et statiques sont parfois appelées constantes. Tous les champs des interfaces sont appelés constantes, car ils sont définitifs et statiques par défaut.

entrez la description de l'image ici

Ressource d'image: Statique final


15

Pour ajouter aux réponses existantes, permettez-moi d'essayer avec une image:

Un taux d'intérêt de 2% est appliqué à TOUS les comptes d'épargne. Il est donc statique .

Un équilibre doit être individuel , il n'est donc pas statique.

entrez la description de l'image ici


13

Cette discussion a jusqu'à présent ignoré les considérations relatives au chargeur de classe. À strictement parler, les champs statiques Java sont partagés entre toutes les instances d'une classe pour un chargeur de classe donné .


1
Cela a été mentionné par Apocalisp dans les commentaires sur la réponse de Merhdad.
Zach Langley

1
Bon point. Beaucoup de gens ne le savent pas, mais une fois que vous commencez à jouer avec les chargeurs de classe, cela devient très important.
sleske

2
C'est vrai, mais cela ne répond pas à la question. Il aurait dû être publié en tant que commentaire.
Marquis de Lorne

7

Un champ peut être affecté à la classe ou à une instance d'une classe. Par défaut, les champs sont des variables d'instance. En utilisant staticle champ devient une variable de classe, il y a donc un et un seul clock. Si vous apportez des modifications à un seul endroit, il est visible partout. Les variables d'instance sont modifiées indépendamment les unes des autres.


6

Le mot static- clé est utilisé pour désigner un champ ou une méthode comme appartenant à la classe elle-même et non à l'instance. À l'aide de votre code, si l'objet Clockest statique, toutes les instances de la Helloclasse partageront ce Clockmembre de données (champ) en commun. Si vous le rendez non statique, chaque instance individuelle de Hellopeut avoir un uniqueClock champ .

Le problème est que vous avez ajouté une méthode principale à votre classe Helloafin de pouvoir exécuter le code. Le problème ici est que la méthode principale est statique et en tant que telle, elle ne peut pas faire référence à des champs ou des méthodes non statiques à l'intérieur. Vous pouvez résoudre ce problème de deux manières:

  1. Rendre tous les champs et méthodes de la Helloclasse statiques afin qu'ils puissent être référencés à l'intérieur du principal méthode . Ce n'est vraiment pas une bonne chose à faire (ou la mauvaise raison pour rendre un champ et / ou une méthode statique)
  2. Créez une instance de votre Helloclasse à l'intérieur de la méthode principale et accédez à tous ses champs et méthodes comme ils étaient destinés à l'origine.

Pour vous, cela signifie la modification suivante de votre code:

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

En Java, le staticmot - clé peut simplement être considéré comme indiquant ce qui suit:

"sans égard ni relation avec un cas particulier"

Si vous pensez de staticcette manière, il devient plus facile de comprendre son utilisation dans les différents contextes dans lesquels il est rencontré:

  • Un staticchamp est un champ qui appartient à la classe plutôt qu'à une instance particulière

  • Une staticméthode est une méthode qui n'a aucune notion de this; il est défini sur la classe et ne connaît aucune instance particulière de cette classe, sauf si une référence lui est transmise

  • Une staticclasse membre est une classe imbriquée sans aucune notion ou connaissance d'une instance de sa classe englobante (sauf si une référence à une instance de classe englobante lui est transmise)


5

Statique fait du membre d'horloge un membre de classe au lieu d'un membre d'instance. Sans le mot clé statique, vous auriez besoin de créer une instance de la classe Hello (qui a une variable membre d'horloge) - par exemple

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

5

les méthodes statiques n'utilisent aucune variable d'instance de la classe dans laquelle elles sont définies. Une très bonne explication de la différence peut être trouvée sur cette page


5

J'ai développé un penchant pour les méthodes statiques (uniquement, si possible) dans les classes "helper".

La classe appelante n'a pas besoin de créer une autre variable membre (instance) de la classe d'assistance. Vous appelez simplement les méthodes de la classe d'assistance. La classe d'assistance est également améliorée car vous n'avez plus besoin d'un constructeur et vous n'avez besoin d'aucune variable membre (instance).

Il y a probablement d'autres avantages.


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

Peut également penser à des membres statiques n'ayant pas de pointeur "this". Ils sont partagés entre toutes les instances.


3

Comprendre les concepts statiques

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

    }
}

Seconde classe

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

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

2

main() est une méthode statique qui a deux restrictions fondamentales:

  1. La méthode statique ne peut pas utiliser un membre de données non statique ni appeler directement une méthode non statique.
  2. this()et super()ne peut pas être utilisé dans un contexte statique.

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

Sortie: erreur de compilation


1

Variables statiques accessibles uniquement dans les méthodes statiques, donc lorsque nous déclarons les variables statiques, ces méthodes getter et setter seront des méthodes statiques

les méthodes statiques sont un niveau de classe auquel nous pouvons accéder en utilisant le nom de classe

Voici un exemple pour les getters et setters de variables statiques:

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

Une question a été posée ici sur le choix du mot «statique» pour ce concept. C'était dupé à cette question, mais je ne pense pas que l'étymologie ait été clairement abordée. Donc...


Cela est dû à la réutilisation des mots clés, en commençant par C.

Considérez les déclarations de données en C (à l'intérieur d'un corps de fonction):

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

La variable foo est créée sur la pile lorsque la fonction est entrée (et détruite lorsque la fonction se termine). En revanche, le bar est toujours là, donc c'est «statique» dans le sens de l'anglais courant - ça ne va nulle part.

Java et les langages similaires ont le même concept pour les données. Les données peuvent être allouées par instance de la classe (par objet) ou une fois pour la classe entière. Étant donné que Java vise à avoir une syntaxe familière pour les programmeurs C / C ++, le mot clé «statique» est approprié ici.

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

Enfin, nous arrivons aux méthodes.

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

Sur le plan conceptuel, il existe une instance de foo () pour chaque instance de la classe C. Il n'y a qu'une seule instance de bar () pour toute la classe C. "est à nouveau un choix judicieux, surtout si vous ne voulez pas ajouter plus de mots-clés réservés à votre langue.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.