Combien d’objects de chaîne en Java?

Mon ami m’a envoyé une question qu’il a vue en un seul examen pour la certificateion Java sur les objects ssortingng:

Ssortingng makeSsortingngs(){ Ssortingng s = "HI"; s = s + "5"; s = s.subssortingng(0,1); s = s.toLowerCase(); return s.toSsortingng(); } 

Combien d’objects de chaîne seront créés lorsque cette méthode est appelée? La réponse correcte à l’examen a été 3. Mais je pense que c’est cinq.

  1. “SALUT”
  2. “5”
  3. “HI5”
  4. “H”
  5. “h”

Ai-je tort?

 Ssortingng makeSsortingngs() { Ssortingng s = "HI"; //Ssortingng literal s = s + "5"; //concatenation creates new Ssortingng object (1) s = s.subssortingng(0,1); //creates new Ssortingng object (2) s = s.toLowerCase(); //creates new Ssortingng object (3) return s.toSsortingng(); //returns already defined Ssortingng } 

En ce qui concerne la concaténation, lors de la création d’une nouvelle chaîne, JVM utilise SsortingngBuilder , à savoir:

 s = new SsortingngBuilder(s).append("5").toSsortingng(); 

toSsortingng() pour un SsortingngBuilder est:

 public Ssortingng toSsortingng() { return new Ssortingng(value, 0, count); //so a new Ssortingng is created } 

subssortingng crée un nouvel object Ssortingng à moins que la Ssortingng entière ne soit indexée:

 public Ssortingng subssortingng(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > count) { throw new SsortingngIndexOutOfBoundsException(endIndex); } if (beginIndex > endIndex) { throw new SsortingngIndexOutOfBoundsException(endIndex - beginIndex) } return ((beginIndex == 0) && (endIndex == count)) ? this : new Ssortingng(offset + beginIndex, endIndex - beginIndex, value); } 

toSsortingng() ne crée PAS une nouvelle chaîne:

 public Ssortingng toSsortingng() { return this; } 

toLowerCase() est une méthode assez longue, mais il suffit de dire que si la Ssortingng n’est pas déjà en minuscule, elle renverra une new Ssortingng .

Étant donné que la réponse fournie est 3 , comme Jon Skeet l’a suggéré, nous pouvons supposer que les deux littéraux Ssortingng sont déjà dans le pool Ssortingng. Pour plus d’informations sur l’ajout de chaînes dans le pool, voir Questions sur le pool de chaînes Java .

s = s + "5";

Est traduit à:

 Ssortingng s = new SsortingngBuilder(s).append("5").toSsortingng(); 

Pour l’instant, un object est créé.


 s = s.subssortingng(0,1); 

Crée une nouvelle chaîne.


 s = s.toLowerCase(); 

Crée un nouvel object.


 return s.toSsortingng(); 

Ne crée pas de chaîne, il retourne une chaîne déjà créée.

Certaines des autres réponses ont du sens, mais qu’en est-il du littéral de chaîne?

 Ssortingng s = "HI"; 

Pour les littéraux de chaîne, lorsqu’un fichier .java est compilé dans un fichier .class, tous les littéraux de chaîne sont notés d’une manière particulière, comme toutes les constantes. Lorsqu’une classe est chargée (notez que le chargement se produit avant l’initialisation), la machine virtuelle Java passe en revue le code de la classe et recherche les chaînes de caractères.

Lorsqu’il en trouve un, il vérifie si une chaîne équivalente est déjà référencée depuis le tas. Sinon, il crée une instance Ssortingng sur le tas et stocke une référence à cet object dans la table des constantes.

Une fois qu’une référence est faite à cet object de chaîne, toute référence à cette chaîne littérale tout au long de votre programme est simplement remplacée par la référence à l’object référencé à partir du pool de littéral de chaîne.

Par conséquent, il devrait y avoir quatre objects Java, bien que lorsque la même méthode est appelée à plusieurs resockets, il n’y aurait que trois objects, car dans l’application, le groupe littéral de chaîne contient le littéral “HI”.

En outre, pour plus d’informations sur les raisons pour lesquelles de nouveaux objects sont créés lorsque les blocs de méthode ci-dessus sont utilisés, nous pouvons également vérifier les codes de hachage qui sont différents pour les différentes chaînes ( Ssortingng étant immuable).

  public static void main(Ssortingng[] args) { NumberOfSsortingng str = new NumberOfSsortingng(); Ssortingng s = str.makeSsortingngs(); System.out.println(s.hashCode()); } public Ssortingng makeSsortingngs() { Ssortingng s = "HI"; System.out.println(s.hashCode()); s = s + "5"; System.out.println(s.hashCode()); s = s.subssortingng(0, 1); System.out.println(s.hashCode()); s = s.toLowerCase(); System.out.println(s.hashCode()); return s.toSsortingng(); } 

Vous obtenez la sortie suivante:

 2305 71508 72 104 104 

Ne devrions-nous pas compter dans l’object littéral Ssortingng dans l’exemple ci-dessus?