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

Langage Java Discussion :

Question théorique sur le langage


Sujet :

Langage Java

  1. #1
    Nouveau membre du Club
    Inscrit en
    Mars 2005
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 36
    Points : 36
    Points
    36
    Par défaut Question théorique sur le langage
    Bonjour,

    J'ai une question théorique à vous soumettre. C'est juste un petit doute autour du langage en lui-même...

    Je me demande où faut-il le mieux placer la déclaration d'une variable...

    Voici la solution la plus sure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Object a = null;
    while (untest) {
       a = fonctionRenvoyantUnObjet(...);
       //Divers traitements ensuite
    }
    Voilà la solution la plus concise :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    while (untest) {
       Object a = fonctionRenvoyantUnObjet(...);
       //Divers traitements ensuite
    }
    Je pense que pour la seconde solution, à l'exécution, le programme ne réserve pas à chaque itération l'espace mémoire pour la variable a.
    A mon avis, lors de la compilation, la déclaration de la variable a est placée juste avant l'entrée dans la boucle.

    Donc pour moi, la seconde possibilité est à préférer pour sa concision (surtout si on utilise plusieurs variables dans une boucle...

    Qu'en pensez-vous ?

    Je sais c'est débile mais bon...

    Nico

  2. #2
    in
    in est déconnecté
    Membre expérimenté Avatar de in
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    1 612
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 612
    Points : 1 718
    Points
    1 718
    Par défaut
    ma réponse va peut être sembler naïve, mais bon je me lance ... comme ça ça me permettra d'avoir des éclaircissements ...

    et bien je dirais que pour la seconde version, une nouvelle référence est créée à chaque fois.

    pour la première solution, la référence (enfin l'adresse en mémoire) est la même, il n'y a pas de réallocation de mémoire.

    donc moi, même s'il y a une ligne de plus, je préfère la première solution. Ya moins d'interaction système. En même temps, comme il s'agit d'un Objet, c'est peut être un cas particulier, genre pointeur sur une autre adresse mémoire.

    [EDIT] en fait j'ai mal lu ton post. Désolé je suis un peu à côté de la plaque pour ma réponse.

  3. #3
    BiM
    BiM est déconnecté
    Expert éminent sénior
    Avatar de BiM
    Femme Profil pro
    Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT
    Inscrit en
    Janvier 2005
    Messages
    7 796
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7 796
    Points : 10 765
    Points
    10 765
    Par défaut
    J'ai pas le même point de vue. La première utilisation, tu crées la variable et elle est utilisable pendant tout le temps d'exécution avant, pendant et après la boucle, réservation de mémoire inutile.

    La seconde solution te permet de libérer la mémoire dès le tour de boucle finit à chaque fois. Si ton application a besoin de cet espace mémoire, il reviendra pour le prendre. Par contre, je pense que si une autre application tourne à côté, cette mémoire ne lui sera pas libérée (à vérifier).

  4. #4
    Nouveau membre du Club
    Inscrit en
    Mars 2005
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 36
    Points : 36
    Points
    36
    Par défaut
    Ce n'est pas un problème, c'est vraiment juste une question que je me pose (je passe des après midi passionantes

    Quand on parle d'espace mémoire, on est bien d'accord qu'on parle juste d'un espace mémoire pour une adresse (pointant sur l'objet retourné par la pseudo fonction), pas l'espace mémoire nécessaire pour stocker une instance de l'objet.

  5. #5
    BiM
    BiM est déconnecté
    Expert éminent sénior
    Avatar de BiM
    Femme Profil pro
    Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT
    Inscrit en
    Janvier 2005
    Messages
    7 796
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7 796
    Points : 10 765
    Points
    10 765
    Par défaut
    Nous sommes d'accord.

  6. #6
    Membre habitué Avatar de White Rabbit
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 122
    Points : 148
    Points
    148
    Par défaut
    Ce n'est pas un problème de (ré)allocation de mémoire. Mais de portée de variable.

    Dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Object a = null;
    while (untest) {
       a = fonctionRenvoyantUnObjet(...); //Divers traitements ensuite
    }
    La variable a est accessible à l'exterieur et à l'interieur du bloc while délimité par les {}.

    Dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    while (untest) {
       Object a = fonctionRenvoyantUnObjet(...); //Divers traitements ensuite
    }
    La variable a n'est accessible qu'à l'interieur du bloc while délimité par les {}.

  7. #7
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 867
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 867
    Points : 22 927
    Points
    22 927
    Billets dans le blog
    53
    Par défaut
    Et moi je me dit qu'il faudrai verifier le byte-code produit par la compilation de ces deux methodes pour verifier quelles optimisations le compilateur aurait pu eventuellement y introduire (avec le code tel quel : a n'est pas utilise a l'exterieur de la boucle).

  8. #8
    BiM
    BiM est déconnecté
    Expert éminent sénior
    Avatar de BiM
    Femme Profil pro
    Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT
    Inscrit en
    Janvier 2005
    Messages
    7 796
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7 796
    Points : 10 765
    Points
    10 765
    Par défaut
    White Rabbit : Je l'ai déjà dit mais d'une autre façon.

  9. #9
    Nouveau membre du Club
    Inscrit en
    Mars 2005
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 36
    Points : 36
    Points
    36
    Par défaut
    Effectivement il y a une question de portée. Dans le second cas, a n'est visible que dans le while (c'est une des raisons qui me font préférer cette façon). Pour être plus précis, elle est visible seulement à partir de sa déclaration dans le while évidemment.

    Mais pour moi, comme le dit bouye, il faudrait savoir ce que fait le compilateur dans ces 2 cas.

    Je pense que dans une boucle contenant des déclarations de variables, le compilateur fait en sorte que toutes les variables soient en pratique déclarées en amont de la boucle une fois pour toute. Mais j'ai peut être tort...

  10. #10
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Question intérressante !

    Personnellement je préfère largement la seconde solution, afin de limiter le scope de la variable...


    Mais par curiosité j'ai tester le code suivant :
    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
    21
    22
    23
    24
    25
    26
    27
     
    public class Main {
     
        private boolean untest = true;
     
        public Object fonctionRenvoyantUnObjet() {
            return "TEST";
        }
     
        public void method1() {
            Object a = null;
            while (untest) {
                   a = fonctionRenvoyantUnObjet();
                System.out.println(a);
            }
     
        }
     
     
        public void method2() {
            while (untest) {
                   Object a = fonctionRenvoyantUnObjet();
                System.out.println(a);
            }
     
        }
    }
    Après une compilation/décompilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    javac Main.java
    javah -c Main
    J'obtient le bytecode suivant :
    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
    21
    22
    23
    24
    25
    26
    27
    28
    29
    public void method1();
      Code:
       0:   aconst_null
       1:   astore_1
       2:   aload_0
       3:   getfield        #2; //Field untest:Z
       6:   ifeq    24
       9:   aload_0
       10:  invokevirtual   #4; //Method fonctionRenvoyantUnObjet:()Ljava/lang/Object;
       13:  astore_1
       14:  getstatic       #5; //Field java/lang/System.out:Ljava/io/PrintStream;
       17:  aload_1
       18:  invokevirtual   #6; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       21:  goto    2
       24:  return
    
    public void method2();
      Code:
       0:   aload_0
       1:   getfield        #2; //Field untest:Z
       4:   ifeq    22
       7:   aload_0
       8:   invokevirtual   #4; //Method fonctionRenvoyantUnObjet:()Ljava/lang/Object;
       11:  astore_1
       12:  getstatic       #5; //Field java/lang/System.out:Ljava/io/PrintStream;
       15:  aload_1
       16:  invokevirtual   #6; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       19:  goto    0
       22:  return
    Je ne suis pas habitué à lire du bytecode, et je peux me tromper...
    Mais le bytecode de la première méthode contient 2 instructions en plus, qui semble correspondre à l'initialisation de la variable à null...
    Le reste étant strictement identique si ce n'est les numéro d'instruction des sauts (ifeq et goto).


    Bref : il vaut mieux laisser ce type d'optimisation au compilateur...


    a++

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 194
    Points : 234
    Points
    234
    Par défaut
    Citation Envoyé par adiGuba
    Bref : il vaut mieux laisser ce type d'optimisation au compilateur...
    Salut,

    Je viens d'effectuer des tests de rapidité en lançant les deux boucles suivantes :

    Attention, les résultats publiés dans ce post sont totalement faux, je me suis trompé dans l'instertion du code à tester



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	//déclaration externe
    	Object obj = null;
    	for(int i=0; i<1000; i++) {
    		obj = new Integer(i);
    	}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    	//déclaration local
    	for(int i=0; i<1000; i++) {
    		Object obj = new Integer(i);
    	}
    Chaque boucle est placée dans une méthode qui est elle-même appelée mille fois. Et le résultat est défrisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    externe : 105413
    local : 31
    A titre de comparaison, si on compare non plus des boucles mais des méthodes appelées en boucles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Test {
    	int i = 0;
    	Object obj = null;
     
    	void local() {
    		Object obj = new Integer(i++);
    	}
     
    	void instance() {
    		obj = new Integer(i++);
    	}
    La différence est moins importante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    instance : 111
    local : 8
    Dans ce dernier cas, je pense que la déclaration d'une variable locale est de toute façon préférable car elle pose généralement moins de problèmes en cas d'accès par des threads concurrents.

    Réédité pour supprimer le smiley

  12. #12
    Membre régulier
    Inscrit en
    Février 2006
    Messages
    93
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 93
    Points : 109
    Points
    109
    Par défaut
    Ah bah ca c'est etrange!!

    J'ai refait les memes tests que toi tellement je ne pouvait en croire mes yeux (surtout pour le premier!!). Mais je trouve des temps totalement comparables et ce quel que soit le nombre d'iteration ou le type d'objet instancie, la difference est de l'ordre de 1% voire moins et pas toujours dans le meme sens selon l'essai... bizarre...

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 194
    Points : 234
    Points
    234
    Par défaut
    Citation Envoyé par Babaôrom
    Ah bah ca c'est etrange!!

    J'ai refait les memes tests que toi tellement je ne pouvait en croire mes yeux (surtout pour le premier!!). Mais je trouve des temps totalement comparables et ce quel que soit le nombre d'iteration ou le type d'objet instancie, la difference est de l'ordre de 1% voire moins et pas toujours dans le meme sens selon l'essai... bizarre...


    Heureusement qu'il y a des gens qui suivent !
    Je reviens de vacances et j'ai un peu la tête ailleurs

    Je me suis trompé dans mon code de test, j'aurais dû être plus sérieux compte tenu de la différence abhérante entre les deux résultats !

    Désolé donc pour ceux qui ont déjà lu mon post, je le réédite pour prévenir que je me suis planté !

  14. #14
    Membre actif
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    194
    Détails du profil
    Informations personnelles :
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Juin 2006
    Messages : 194
    Points : 234
    Points
    234
    Par défaut
    Citation Envoyé par had35
    Salut,

    Je viens d'effectuer des tests de rapidité en lançant les deux boucles suivantes :

    Attention, les résultats publiés dans ce post sont totalement faux, je me suis trompé dans l'insertion du code à tester



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	//déclaration externe
    	Object obj = null;
    	for(int i=0; i<1000; i++) {
    		obj = new Integer(i);
    	}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    	//déclaration local
    	for(int i=0; i<1000; i++) {
    		Object obj = new Integer(i);
    	}
    Chaque boucle est placée dans une méthode qui est elle-même appelée mille fois. Et le résultat est défrisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    externe : 105413
    local : 31
    A titre de comparaison, si on compare non plus des boucles mais des méthodes appelées en boucles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Test {
    	int i = 0;
    	Object obj = null;
     
    	void local() {
    		Object obj = new Integer(i++);
    	}
     
    	void instance() {
    		obj = new Integer(i++);
    	}
    La différence est moins importante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    instance : 111
    local : 8
    Dans ce dernier cas, je pense que la déclaration d'une variable locale est de toute façon préférable car elle pose généralement moins de problèmes en cas d'accès par des threads concurrents.

    Réédité pour supprimer le smiley

  15. #15
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Moi je me pose une autre question:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    boolean b = false;
    while(!b) {
        b = fonction();
    }
    Ici il est normal de déclarer le b à l'extérieur du while...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    do {
        boolean b = fonction();
    } while(!b); //ne marche pas
    Pourquoi dans une boucle do-while on ne peut pas mettre la déclaration à l'intérieur?

  16. #16
    BiM
    BiM est déconnecté
    Expert éminent sénior
    Avatar de BiM
    Femme Profil pro
    Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT
    Inscrit en
    Janvier 2005
    Messages
    7 796
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7 796
    Points : 10 765
    Points
    10 765
    Par défaut
    Parce que le test sur b est hors de portée.

    Regardes ton code (d'ou tu as oublié une accolade justement) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    do
    {
        boolean b = fonction();
    }
    while(!b);
    Le bloc se positionne juste après le do et juste avant le while. La variable b a été déclarée à l'intérieur du bloc. Le while n'étant pas compris dans le bloc, la variable n'existe plus à ce moment (en tout cas dansle programme).

  17. #17
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par BiM
    Parce que le test sur b est hors de portée.

    Regardes ton code (d'ou tu as oublié une accolade justement) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    do
    {
        boolean b = fonction();
    }
    while(!b);
    Le bloc se positionne juste après le do et juste avant le while. La variable b a été déclarée à l'intérieur du bloc. Le while n'étant pas compris dans le bloc, la variable n'existe plus à ce moment (en tout cas dansle programme).
    Exact

  18. #18
    Membre émérite
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Points : 2 411
    Points
    2 411
    Par défaut
    Simple remarque...

    Qui à faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    do
    {
        boolean b = fonction();
    }
    while(!b);
    autant faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    do
    {
     
    }
    while(!fonction());
    Sinon en fait je dirai comme adiGuba, autant laisser la MV se débrouiller, moi je ne m'en inquette que dans des besoins de portée, sinon je fais un peu selon mon humeur actuelle

    Fred

  19. #19
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par mavina
    Simple remarque...

    Qui à faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    do
    {
        boolean b = fonction();
    }
    while(!b);
    autant faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    do
    {
     
    }
    while(!fonction());
    Certes, mais ce n'était qu'un exemple, on suppose qu'on utilise la variable juste après son affectation dans la boucle

  20. #20
    BiM
    BiM est déconnecté
    Expert éminent sénior
    Avatar de BiM
    Femme Profil pro
    Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT
    Inscrit en
    Janvier 2005
    Messages
    7 796
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultante/Formatrice BIRT & Ingénieur Java/J2EE/GWT

    Informations forums :
    Inscription : Janvier 2005
    Messages : 7 796
    Points : 10 765
    Points
    10 765
    Par défaut
    Ceci suffit :

Discussions similaires

  1. Réponses: 18
    Dernier message: 02/06/2008, 23h20
  2. Réponses: 3
    Dernier message: 04/04/2008, 19h02
  3. question théorique sur le stockage des données
    Par jp_rennes dans le forum Administration
    Réponses: 1
    Dernier message: 18/09/2006, 19h28
  4. question théorique sur le mot class
    Par stgi02 dans le forum C++
    Réponses: 3
    Dernier message: 01/05/2006, 16h11
  5. Question théorique sur les normales
    Par Pedro dans le forum DirectX
    Réponses: 5
    Dernier message: 16/10/2005, 20h24

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