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 :

Combien de variable de type String sont instanciées à chaque exécution ?


Sujet :

Langage Java

  1. #1
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut Combien de variable de type String sont instanciées à chaque exécution ?
    Salut,

    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
    import java.util.*;
    import java.lang.*;
    import java.io.*;
     
    class Ideone
    {
        public static void main (String[] args) throws java.lang.Exception
        {
        String str = new String("") ;
        for(int i = 0; i < 10; i++) 
              str += "i = " + i + " i² = " + i*i + "\n";
          System.out.println(str);
     
        }
    }
    Combien de variable de type String sont instanciées à chaque exécution de la ligne 11 ?

    Une seule ? Une pour chaque addition ?

    Merci.

  2. #2
    Membre chevronné
    Avatar de provirus
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2009
    Messages
    248
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2009
    Messages : 248
    Par défaut
    Bonjour,

    la réponse est: énormément
    Chaque nouveau String est une instanciation. Par contre, 2 fois la même chaine est la même instance (en d'autres mots, si tu as 3 Strings: "allo", "monde" et "allo", tu as 2 instances au total puisque "allo" va pointer sur la même instance).

    En partant de là, voici les instances en ordre (de haut en bas et de droite à gauche:
    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
     
    1- "" (dans str)
    2- "\n"
    3- "0\n"
    4- " i² = 0\n"
    5- "0 i² = 0\n"
    6- "i = 0 i² = 0\n" (str à la fin de la boucle)
     
    (fin de la première boucle et on est déjà à 6)
    2- "\n" (c'est la même que la #2)
    7- "1\n"
    8- " i² = 1\n"
    9- "1 i² = 1\n"
    10- "i = 1 i² = 1\n" 
    11- "i = 0 i² = 0\ni = 1 i² = 1\n" (str à la fin de la boucle)
     
    (fin de la deuxième boucle et ça continue...)
    Pour éviter tout cela, le mieux est d'utiliser un StringBuilder.

  3. #3
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    De variable String ? Aucune. On n'instancie pas une variable, on instancie une classe.

    Si la question est, combien d'objets de type String sont construits à chaque exécution de la ligne 11, eh bien, chose rare en Java, ça dépend des choix du compilateur.

    La règle de base, décrit deux temps :
    #1 - convertir chaque opérande de la concaténation en String. Ici il n'y en a que deux qui ne sont pas des String : i et i*i. Ça fait déjà deux String à chaque exécution.
    #2 - chaque opération de concaténation entre deux opérandes, crée une nouvelle String résultat. Ici nous avons 5 signes + donc 5 concaténations, donc création de 5 Strings.
    Au total ça devrait faire 7.

    Mais pour des raisons d'optimisation une certaine liberté est laissée au compilateur. La String résultante calculée par l'expression, doit être équivalente à ce que produiraient les règles énoncées. Mais le compilateur n'est pas tenu de réellement créer les String en question, et peut décider à la place d'utiliser d'autres techniques pour générer moins d'objets intermédiaires, puisque ces objets sont de toute façon inaccessibles et sans usage en dehors des étapes de calcul.

    Ainsi un compilateur a le droit de faire les conversions et concaténations en une seule étape, par exemple en usant d'un StringBuilder intermédiaire.
    Ce qui ne crée qu'une seule String, pour stocker le résultat dans la variable.

    Si nous regardons comment le compilateur javac 1.8 d'Oracle compile ce bout de code, nous voyons qu'il instancie en effet un StringBuilder, et qu'il appelle append(String) et append(int) dessus. Puis la String finale est générée avec un appel à toString() sur ce StringBuilder, ce qui crée donc une String. Une seule.
    Reste à voir si les appels à append(int) n'en créeraient pas aussi. Cela ne dépend pas du compilateur, mais de la JRE : plus exactement de l'implémentation de StringBuilder. Si nous regardons celle de la JRE 1.8 d'Oracle, nous voyons que append(int) ne crée pas de String : à la place il calcule les chiffres du nombre et les ajoute à la volée dans le StringBuilder avec des accès optimisés.


    Conclusion : avec le compilateur et la JRE 1.8 d'Oracle, il n'y a création que d'une seule String à la ligne 11.
    D'autres compilateurs et d'autres JRE pourraient donner d'autres résultats.

    Mon conseil : il n'y a pas lieu de penser que les autres feraient beaucoup moins bien. Appeler StringBuilder est une évidence et il n'y a pas de raison de croire qu'un compilateur n'y aurait pas pensé.
    Si la concaténation est en une seule expression, on peut raisonnablement compter sur le compilateur pour optimiser l'opération correctement.
    Par contre, si elle est en plusieurs instructions, le compilateur n'est pas autorisé à adapter son comportement et il vaut mieux, soit se ramener à une seule expression, soit utiliser StringBuilder soi-même.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par thelvin Voir le message
    Conclusion : avec le compilateur et la JRE 1.8 d'Oracle, il n'y a création que d'une seule String à la ligne 11.
    Il y a bien une seule String créé à la ligne 11... mais comme cette ligne est à l'intérieur d'une boucle cela va générer plusieurs String (et même plusieurs StringBuilder), ce qui se révèle très consommateur en mémoire !
    Bien sûr sur 10 itérations c'est quasi invisible... mais cela monte de manière exponentielle avec le nombre d'itération.

    En effet chaque iteration va créer deux objets : un StringBuilder et un String.
    Du coup on ne profite pas de la capacité du StringBuilder à se dimensionner correctement, puisqu'on en crée un nouveau à chaque fois.
    C'est comme si on avait écrit ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    String str = "";
    for(int i = 0; i < 10; i++) 
        str = new StringBuilder(str).append("i = ").append(i).append(" i² = ").append(i*i).append("\n").toString();

    Bref il vaut mieux utiliser un seul StringBuilder comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	StringBuilder sb = new StringBuilder();
    	for(int i = 0; i < 10; i++)
    	    sb.append("i = ").append(i).append(" i² = ").append(i*i).append("\n");
    	String str = sb.toString();

    Pour info, en calculant le temps d'exécution j'obtiens les résultats suivant (StringBuilder / opérateur +) :
    • 1 000 itérations : 1ms / 31ms
    • 10 000 itérations : 9ms / 1,5s
    • 100 000 itérations : 37ms / 167s (près de 3 minutes)
    • 1 000 000 itérations : 128ms / (je n'ai pas eu le courage d'attendre).
    • 10 000 000 itérations : 1,2s / (je n'ai pas eu le courage d'attendre).



    a++

  5. #5
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Combien de variable de type String sont instanciées à chaque exécution de la ligne 11 ?
    Une seule ? Une pour chaque addition ?
    Si je me réfère à la question, sauf erreur de ma part, la réponse devrait être : une pour chaque addition

    Mais en tenant compte de l'optimisation du compilateur, ça pourrait aussi être une seule (s'il a généré les opérations sur un StringBuilder ou équivalent)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Mais en tenant compte de l'optimisation du compilateur, ça pourrait aussi être une seule (s'il a généré les opérations sur un StringBuilder ou équivalent)
    Un compilateur qui utiliserait un seul StringBuilder sur une boucle for ? Ca me semble étonnant. Et dans tous les cas possible uniquement sur des exemples tres simples...

  7. #7
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    La compilation du code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public static void main(String[] args)
    {
            String str = new String("");
     
            for (int i = 0; i < 10; i++)
            {
                str += "i = " + i + " i² = " + i * i + "\n";
            }
            System.out.println(str);
    }
    Donne le résultat (décompilé à partir du .class)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public static void main(String args[])
    {
            String str = new String("");
            for(int i = 0; i < 10; i++)
                str = (new StringBuilder(String.valueOf(str))).append("i = ").append(i).append(" i\262 = ").append(i * i).append("\n").toString();
     
            System.out.println(str);
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    ok. Donc, comme attendu, on a bien un StringBuilder par iteration (et non un seul utilisé sur la boucle for). Et on va retrouver la consommation mémoire et le temps d'execution donnés par adiGuba...

  9. #9
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    D'un point de vue de l'optimisation, le mieux serait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 10; i++)
    {
        sb.append("i = ").append(i).append(" i² = ").append(i * i).append("\n");
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  10. #10
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    D'un point de vue de l'optimisation,
    Ce n'est même pas de l'optimisation. C'est surtout la bonne manière de faire.

    Le type String est immuable, donc il est incorrect de vouloir le modifier comme cela. Ce n'est pas fait pour !


    Les opérateurs += ou + de String permettent de simplifier la création de String, mais cela doit rester du "one-shot" sur une seule instruction.
    Dès que le nombre d'instructions augmente (ou qu'elle fait partie d'une boucle), il faut utiliser StringBuilder.


    a++

  11. #11
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Le type String est immuable, donc il est incorrect de vouloir le modifier comme cela. Ce n'est pas fait pour !
    On dirait que certains l'oublie
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  12. #12
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Salut,

    Tout d'abord merci à tous, vos messages sont instructifs...

    Sinon oui j'ai posé la question pour comparer avec un StringBuilder...

    J'ai regardé les .class je me suis un peu pris la tête car je vois qu'il y a aussi l'idée de décompiler le .class (merci à OButterlin*)

    Citation Envoyé par adiGuba Voir le message

    En effet chaque iteration va créer deux objets : un StringBuilder et un String.
    Du coup on ne profite pas de la capacité du StringBuilder à se dimensionner correctement, puisqu'on en crée un nouveau à chaque fois.
    C'est comme si on avait écrit ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    String str = "";
    for(int i = 0; i < 10; i++) 
        str = new StringBuilder(str).append("i = ").append(i).append(" i² = ").append(i*i).append("\n").toString();
    Je ne vois pas où il crée un objet de type String à chaque itération... Dans le .class ci-dessous je vois qu'un seul "new" dans la boucle, en effet à la ligne 14 on a
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new java.lang.StringBuffer [19]
    Quelques chose doit m'échapper...


    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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    // Compiled from StringTestMemoire1.java (version 1.2 : 46.0, super bit)
    public class StringTestMemoire1 {
     
      // Method descriptor #6 ()V
      // Stack: 1, Locals: 1
      public StringTestMemoire1();
        0  aload_0 [this]
        1  invokespecial java.lang.Object() [8]
        4  return
          Line numbers:
            [pc: 0, line: 2]
          Local variable table:
            [pc: 0, pc: 5] local: this index: 0 type: StringTestMemoire1
     
      // Method descriptor #15 ([Ljava/lang/String;)V
      // Stack: 4, Locals: 3
      public static void main(java.lang.String[] args);
         0  new java.lang.StringBuilder [16]
         3  dup
         4  invokespecial java.lang.StringBuilder() [18]
         7  astore_1 [strB]
         8  iconst_0
         9  istore_2 [i]
        10  goto 53
        13  aload_1 [strB]
        14  new java.lang.StringBuffer [19]
        17  dup
        18  ldc <String "i = "> [21]
        20  invokespecial java.lang.StringBuffer(java.lang.String) [23]
        23  iload_2 [i]
        24  invokevirtual java.lang.StringBuffer.append(int) : java.lang.StringBuffer [26]
        27  ldc <String " i² = "> [30]
        29  invokevirtual java.lang.StringBuffer.append(java.lang.String) : java.lang.StringBuffer [32]
        32  iload_2 [i]
        33  iload_2 [i]
        34  imul
        35  invokevirtual java.lang.StringBuffer.append(int) : java.lang.StringBuffer [26]
        38  ldc <String "\n"> [35]
        40  invokevirtual java.lang.StringBuffer.append(java.lang.String) : java.lang.StringBuffer [32]
        43  invokevirtual java.lang.StringBuffer.toString() : java.lang.String [37]
        46  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [41]
        49  pop
        50  iinc 2 1 [i]
        53  iload_2 [i]
        54  bipush 111
        56  if_icmple 13
        59  return
          Line numbers:
            [pc: 0, line: 12]
            [pc: 8, line: 13]
            [pc: 13, line: 14]
            [pc: 50, line: 13]
            [pc: 59, line: 18]
          Local variable table:
            [pc: 0, pc: 60] local: args index: 0 type: java.lang.String[]
            [pc: 8, pc: 60] local: strB index: 1 type: java.lang.StringBuilder
            [pc: 10, pc: 59] local: i index: 2 type: int
    }



    * Pourrais-tu me dire comment tu as fait ? C'est possible avec Eclipse ?

  13. #13
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Je ne vois pas où il crée un objet de type String à chaque itération... Dans le .class ci-dessous je vois qu'un seul "new" dans la boucle, en effet à la ligne 14 on a
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new java.lang.StringBuffer [19]
    Quelques chose doit m'échapper...
    Ben c'est bien beau de construire un StringBuffer, mais un StringBuffer n'est pas une String. Pour avoir la String demandée dans la variable str à chaque itération, il faut bien construire cette String.
    Comme je l'ai dit, cela se fait à l'appel de toString() sur l'objet StringBuffer (dont on peut constater, en regardant l'implémentation, qu'il fait bien new String.)

    À noter que s'il utilise StringBuffer au lieu de StringBuilder, il est pas tout neuf ton compilateur .
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  14. #14
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Ben c'est bien beau de construire un StringBuffer, mais un StringBuffer n'est pas une String. Pour avoir la String demandée dans la variable str à chaque itération, il faut bien construire cette String.
    Comme je l'ai dit, cela se fait à l'appel de toString() sur l'objet StringBuffer (dont on peut constater, en regardant l'implémentation, qu'il fait bien new String.)

    À noter que s'il utilise StringBuffer au lieu de StringBuilder, il est pas tout neuf ton compilateur .
    Oui mais du point de vue mémoire qu'en est-il ? Je veux dire quand il construit la String à partir de l'objet StringBuilder est-ce qu'il y a copie (duplication) de tous les octets ou bien il va juste y avoir une affectation de la référence c’est-à-dire qu'après ça str va pointer sur le même espace mémoire que l'objet StringBuffer (sans qu'il y ait de copie).

    J'ai compilé ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class StringTestMemoire1 {
     
        public static void main(String[] args) {
     
            String str = "";
            for(int i = 0; i < 10; i++) 
                str = new StringBuilder(str).append("i = ").append(i).append(" i² = ").append(i*i).append("\n").toString();
        }
     
    }
    Et j'obtiens ça :

    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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    // Compiled from StringTestMemoire1.java (version 1.2 : 46.0, super bit)
    public class StringTestMemoire1 {
     
      // Method descriptor #6 ()V
      // Stack: 1, Locals: 1
      public StringTestMemoire1();
        0  aload_0 [this]
        1  invokespecial java.lang.Object() [8]
        4  return
          Line numbers:
            [pc: 0, line: 2]
          Local variable table:
            [pc: 0, pc: 5] local: this index: 0 type: StringTestMemoire1
     
      // Method descriptor #15 ([Ljava/lang/String;)V
      // Stack: 3, Locals: 3
      public static void main(java.lang.String[] args);
         0  ldc <String ""> [16]
         2  astore_1 [str]
         3  iconst_0
         4  istore_2 [i]
         5  goto 48
         8  new java.lang.StringBuilder [18]
        11  dup
        12  aload_1 [str]
        13  invokespecial java.lang.StringBuilder(java.lang.String) [20]
        16  ldc <String "i = "> [23]
        18  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [25]
        21  iload_2 [i]
        22  invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder [29]
        25  ldc <String " i² = "> [32]
        27  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [25]
        30  iload_2 [i]
        31  iload_2 [i]
        32  imul
        33  invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder [29]
        36  ldc <String "\n"> [34]
        38  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [25]
        41  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [36]
        44  astore_1 [str]
        45  iinc 2 1 [i]
        48  iload_2 [i]
        49  bipush 10
        51  if_icmplt 8
        54  return
          Line numbers:
            [pc: 0, line: 6]
            [pc: 3, line: 7]
            [pc: 8, line: 8]
            [pc: 45, line: 7]
            [pc: 54, line: 9]
          Local variable table:
            [pc: 0, pc: 55] local: args index: 0 type: java.lang.String[]
            [pc: 3, pc: 55] local: str index: 1 type: java.lang.String
            [pc: 5, pc: 54] local: i index: 2 type: int
    }
    Dans la boucle il n'y a qu'un seul new à la ligne 8 :

    new java.lang.StringBuilder [18]

  15. #15
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 313
    Billets dans le blog
    1
    Par défaut
    Il va y avoir création d'une instance de String à chaque itération parce que String est immuable (une fois créée, elle ne peut plus être modifiée).
    Normalement, chaque instance est créée sur la pile et le tout sera détruit (on ne sait quand) par le GC après la sortie de la méthode (mais je ne suis pas un spécialiste du compilateur, adiGuba devrait t'en dire plus )
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  16. #16
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par Beginner. Voir le message
    Dans la boucle il n'y a qu'un seul new à la ligne 8 :
    Ben voui, et alors ? Tu as juste décompilé une toute petite méthode, là.

    Si tu veux voir tous les new, il va falloir aussi décompiler StringBuilder et toutes les autres classes qu'il appelle.
    ... Ou juste regarder leur code source sans décompiler, ça marche aussi .
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  17. #17
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    J'ai regardé et au bout d'un moment il y a un appel à la fonction getChars qui appelle la fonction System.arraycopy...

    Je ne sais pas si il y a des new dans la fonction System.arraycopy mais en tous cas il y a bien copie des octets..

  18. #18
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    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 482
    Par défaut
    Ne te fie pas à la décompilation. Si elle te donne une idée de comment le compilateur a interprété ton code, ça ne réponds pas à ta question de base car des instances peuvent être créées ailleurs. Voilà une analyse de ton code:

    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
    public class StringTestMemoire1 {
     
        public static void main(String[] args) {
     
            String str = ""; (1)
            for(int i = 0; i < 10; i++) 
                str = new StringBuilder(str)
                            .append("i = ") (3)
                            .append(i)
                            .append(" i² = ") (3)
                            .append(i*i)
                            .append("\n") (3)
                            .toString(); (2)
        }
     
    }
    (2) Comme tu peux le constater dans la source de stringbuilder, http://grepcode.com/file/repository....toString%28%29 , toString crée bien une nouvelle String. On a 10 boucles, on a donc 10 strings.

    (1) peut être plus complexe à comprendre. Dans ton code il n'y a pas de new. Mais cette string vide doit bien être crée quelque part. En réalité c'est le classloader qui va faire le travail en voyant ton code assembleur. Il va au moins instancier une fois ton "" pour qu'il puisse exister. Peut être plus, c'est indéterminé.

    (3) de même que pour 1, chacune doit exister au moins une fois, donc 3 instances supplémentaires.

    Ton code crée donc au moins 14 instances de String, au moins 10 instances de StringBuilder et un nombre indéterminé d'instances de char[] internes à StringBuilder.

  19. #19
    Membre Expert
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    2 910
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 2 910
    Par défaut
    Ok merci bien.

Discussions similaires

  1. convertir une variable de type String en Number
    Par lilbrother974 dans le forum Flash
    Réponses: 13
    Dernier message: 06/09/2006, 08h28
  2. fonction replace et variable de type string
    Par aA189 dans le forum Access
    Réponses: 6
    Dernier message: 11/08/2006, 17h38
  3. [VB] gestion des couleurs des variables de type string
    Par landry005 dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 28/03/2006, 14h36
  4. Ajouter a une variable de type string, un entier
    Par Little-Freud dans le forum SL & STL
    Réponses: 12
    Dernier message: 05/03/2005, 19h33
  5. [VB6] creation de variable de type string dynamiquement
    Par da40 dans le forum VB 6 et antérieur
    Réponses: 10
    Dernier message: 12/06/2003, 16h59

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