IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

Static - pourquoi et comment ça marche?


Sujet :

avec Java

  1. #1
    Membre éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut Static - pourquoi et comment ça marche?
    Bonjour,
    j'ai récupéré un bout de code, et je n'arrive pas à voir pourquoi cela fonctionne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Machin {
    	int i = 1;
     
    	static int j = 3;
    	static { j = 2; }
     
    	Machin() {
    		i = 4;
    		j = 5;
    	}
     
    	public static void main(String ch[])
    	{
    		System.out.println(j);
    		new Machin();
    		System.out.println(j);
    	}
    }
    Pourquoi la ligne 5 fonctionne? Qu'est ce qu'elle représente? C'est de la redéfinition? Pourquoi on ne peut pas le faire sans accolade? Et pourquoi ce n'est pas propre au bloc?
    Ce petit machin me perturbe et je n'arrive pas à l'expliquer logiquement avec ce que je connais de la programmation.

    Merci d'avance.

  2. #2
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    c'est un initialiseur static, qui se comporte comme une espèce de "constructeur" pour les champs statiques, au chargement de la classe (juste après les initialisations des variables statiques, dans l'ordre dans lequel ils sont déclarés dans la classe)...

    Très utile lorsqu'on désire déclarer une constante, mais que la valeur de la constante ne peut être que le résultat d'un calcul complexe au runtime.


    http://docs.oracle.com/javase/tutori...O/initial.html

  3. #3
    Membre éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut
    C'est un peu comme les sous-classes interne dans un bloc : ils n'ont pas de référence récupérable et peuvent être utiliser comme sous code?
    On peut mettre ce que l'on veut comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static { int k; for (k=0; k<10; k++); j=k; }
    Pas mal.

    Merci.

  4. #4
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    Citation Envoyé par dafpp Voir le message
    C'est un peu comme les sous-classes interne dans un bloc
    moui et non, ça me dérange pas mal comme formulation, c'est très impréci...

    il n'y a pas vraiment d'équivalent aux blocs statiques. c'est "du code qui s'exécute une seule fois par chargement de classe, juste après l'initialisation des champs statiques". Rien à voir avec des sous-classes internes ou pas, anonymes ou pas...

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Ca ne s'exécute pas après l'initialisation des champs statiques, ca s'exécute pendant (en fonction de la position du bloc au milieu de champs)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package sandbox;
     
     
     
    public class Machin {
     
    	static int a = 0;
    	static int b = 1;
    	static int c = b;
    	static {b = 5;}
    	static int d = a;
    	static {a = 6;}
    	public static void main(String[] args) {
    		System.out.println("a -> "+a);
    		System.out.println("b -> "+b);
    		System.out.println("c -> "+c);
    		System.out.println("d -> "+d);
     
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    a -> 6
    b -> 5
    c -> 1
    d -> 0
    Mais sérieusement, l'utilisation pour "l'initialisation de champs complexes" est pour moi totalement inappropriée. On peut très bien transférer ce code dans une méthode qui est appelée sur la partie droite de l'assignation.

  6. #6
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Ca ne s'exécute pas après l'initialisation des champs statiques, ca s'exécute pendant (en fonction de la position du bloc au milieu de champs)
    awé en effet, bon autant pour moi... si on commence à s'appuyer sur ce genre de détails, y'a quand même un gros problème...

    Citation Envoyé par tchize_ Voir le message
    Mais sérieusement, l'utilisation pour "l'initialisation de champs complexes" est pour moi totalement inappropriée. On peut très bien transférer ce code dans une méthode qui est appelée sur la partie droite de l'assignation.
    moui mais c'est pas pareil... une méthode, ça porte un nom, et ça peut s'invoquer n'importe quand et par n'importe quel thread.

    le bloc static lui, ne s'exécute qu'une fois, et ne peut plus être invoqué par la suite, et par un seul thread dans un contexte "sûr" (il est impossible que plusieurs threads fassent l'initialisation d'une même classe en même temps, cf. les spécs de la vm concernant l'initialisation des classes)... d'où une notion d'initialisation (du coup on peut coder différement, avec moins de risques)...


  7. #7
    Membre éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut
    Très bien - mieux vaut pas comparer avec quelque chose qui existe-, et ça c'est propre au Java ou à la POO?

  8. #8
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    Hum java je dirais. Je sais pas pour les autres langages, je verrais bien C# avoir un équivalent, mais certainement pas la majorité des autres (php, js, ...)

  9. #9
    Membre éclairé Avatar de dafpp
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2008
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2008
    Messages : 345
    Par défaut
    Ok, merci.

  10. #10
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par Pill_S Voir le message

    moui mais c'est pas pareil... une méthode, ça porte un nom, et ça peut s'invoquer n'importe quand et par n'importe quel thread.

    le bloc static lui, ne s'exécute qu'une fois, et ne peut plus être invoqué par la suite, et par un seul thread dans un contexte "sûr"
    Tu m'explique pourquoi ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    private static Map<String,String> dictionnaire = initDictionnaire();
     
    private static Map<String,String> initDictionnaire() {
        HashMap<String,String> contenu = new HashMap<String,String>();
        contenu.put("Bonjour","Hello");
        contenu.put("Salut", "Hi");
        return contenu;
    }
    est plus sale ou pose problème par rapport à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    private static Map<String,String> dictionnaire = new HashMap<String,String>();
    static {
        dictionnaire.put("Bonjour","Hello");
        dictionnaire.put("Salut", "Hi");
    }
    Allez, voilà une version encore plus sale

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private static Map<String,String> dictionnaire = new HashMap<String,String>(){{
        put("Bonjour","Hello");
        put("Salut", "Hi");
    }}

  11. #11
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    Bah objectivement, ça va être très difficile de trouver des arguments pertinents et indiscutables en défaveur de l'un ou l'autre. Clairement, on peut faire la même chose avec l'une ou l'autre option, cependant les initialiseurs statiques offrent quelques subtilités qui peuvent être intéressantes:

    - le fait que cela soit pas nommé interdit à 100% une invocation non désirée (oui je sais, même un développeur médiocre sait qu'il ne faut pas invoquer plusieurs fois des méthodes d'initialisation, mais là, c'est gravé dans le marbre et garantit par le langage. Même sans javadoc, aucune confusion possible)
    - le fait que cela soit mono-threadé réduit de beaucoup les emmerdes possibles
    - un bloc static peut initialiser plusieurs champs en une seule fois, tout en gérant éventuellement des contraintes de validité d'un champ par rapport à un l'autre (tout en rassemblant ce code à un seul endroit)
    - certainement d'autres auxquelles je n'ai pas pensé...

    Alors c'est sûr que c'est pas non plus une révolution, mais c'est sur ce genre de petits détails mineurs qu'on peut faire la différence entre une bonne API et une TRÈS bonne API... C'est comme la différence entre un marteau normal ou un marteau de charpentier... Les deux servent exactement à la même chose, mais l'un est légèrement supérieur à l'autre dans certaines situations très spécifiques...


  12. #12
    Membre extrêmement actif
    Avatar de MarieKisSlaJoue
    Homme Profil pro
    Ingénieur Cloud
    Inscrit en
    Mai 2012
    Messages
    1 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Roumanie

    Informations professionnelles :
    Activité : Ingénieur Cloud
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2012
    Messages : 1 145
    Billets dans le blog
    20
    Par défaut
    Je profite du débat qui se lance.
    J'ai toujours cru que ça servais à initialiser des valeur de classe anonyme (Car justement on ne peut pas appeler de constructeur pour les initialisé ?)
    On m'a menti ou bien ?
    Ce post à été écrit par un panda
    Apollo 11 - AGC revue de code
    -- qwerty keybord

  13. #13
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 586
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 586
    Par défaut
    Citation Envoyé par Pill_S Voir le message
    - un bloc static peut initialiser plusieurs champs en une seule fois, tout en gérant éventuellement des contraintes de validité d'un champ par rapport à un l'autre (tout en rassemblant ce code à un seul endroit)
    Le genre de choses typiques pour lesquelles j'ai un bloc static : ma classe utilise un certain nombre de données qui varient peu et pas pendant le cycle de vie de l'application. Mais qui sont assez volumineuses et peu adaptées directement dans leur forme finale dans le code source. Donc plutôt en String ou déportées dans un fichier de ressources lu avec getResourceAsStream(). Disons une séquence de ints.
    Je veux leur somme, je veux leur moyenne, mais ça m'intéresse pas de retenir leur nombre ou la séquence complète.

    Faire ça avec un appel de méthode à droite, c'est frustrant : soit je fais deux fois la même chose, soit j'invente des variables statiques intermédiaires juste pour qu'il soit possible de le faire. Avec un bloc static je fais les deux en même temps.

    Citation Envoyé par MarieKisSlaJoue Voir le message
    Je profite du débat qui se lance.
    J'ai toujours cru que ça servais à initialiser des valeur de classe anonyme (Car justement on ne peut pas appeler de constructeur pour les initialisé ?)
    On m'a menti ou bien ?
    Je vois pas franchement le rapport en fait. Si on peut pas appeler de constructeur c'est parce qu'on en a pas besoin, puisque c'est le seul endroit où on construit une instance de la classe. Suffit d'utiliser les variables qui sont dispos à ce moment-là, et les rendre finales si c'est des variables locales.
    À la rigueur un bloc pas static permet de faire quelques initialisations du genre qu'on aurait plutôt mises dans un constructeur, mais un bloc static ne peut pas faire ça puisqu'il n'est exécuté qu'une fois par classe, pas par instance.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  14. #14
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Effectivement, je n'avais pas pensé aux variables liées, merci pour la remarque. Ceci dit, personnellement, j'évite au maximum les états statiques, je trouve plus pratique, pour les situations complexes, d'avoir recours à des singletons. C'est par exemple beaucoup plus facile à unit tester dans différentes conditions. Les champs statiques: faut soit jouer avec les classloaders pour refaire une initialisation statiques, soit lancer chaque test dans sa propre jvm. Un singleton, "suffit" de le réinstancier dans le unit test. Ca reste pas propre, mais c'est faisable :p
    Et autant que possible j'évite aussi les singletons, je leur préfère les scope singleton de spring quand j'ai une application pouvant bénéficier de spring IOC

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. ToAsciiEx, comment cela marche ?
    Par mikyfpc dans le forum C++Builder
    Réponses: 2
    Dernier message: 17/02/2004, 22h39
  2. [MFC] list box : comment ça marche
    Par runn2 dans le forum MFC
    Réponses: 4
    Dernier message: 28/01/2004, 13h36
  3. [SYNEDIT] -> Comment ça marche ?
    Par MaTHieU_ dans le forum C++Builder
    Réponses: 2
    Dernier message: 18/01/2004, 20h11
  4. [TP][Turbo Vision] comment ça marche ??
    Par Costello dans le forum Turbo Pascal
    Réponses: 7
    Dernier message: 05/08/2003, 01h24
  5. [update][req. imbriquee] Comment ca marche ??
    Par terziann dans le forum Langage SQL
    Réponses: 3
    Dernier message: 11/07/2003, 13h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo