14 votes

Pourquoi la classe String a un constructeur de copie ?

Duplicata possible :
Quel est le but de l'expression "new String( )" en Java ?

Si les copies d'objets de classes immuables sont égales aux originaux, alors pourquoi le programme String en Java ont un constructeur de copie ? Est-ce une erreur ou y a-t-il une raison derrière cette implémentation ? Dans la documentation de Java, il est spécifié que :

/**
 * Initializes a newly created {@code String} object so that it represents
 * the same sequence of characters as the argument; in other words, the
 * newly created string is a copy of the argument string. Unless an
 * explicit copy of {@code original} is needed, use of this constructor is
 * unnecessary since Strings are immutable.
 *
 * @param  original
 *         A {@code String}
 */
 public String(String original) {
 ....
 ....}

11voto

dystroy Points 145126

La principale raison de copier une chaîne de caractères est de "coupez le bagage" qui consiste à réduire le tableau de chars sous-jacent à ce qui est nécessaire.

Le tableau de chars sous-jacent peut principalement être trop grand car lorsque vous créez une chaîne de caractères en appelant substring le tableau de caractères peut être partagé entre la nouvelle instance de chaîne et l'instance de chaîne source ; un décalage pointe vers le premier caractère et la longueur est incluse.

L'expression que j'utilise, "coupez le bagage" est tiré du code source du constructeur de copie de chaîne :

  164       public String(String original) {
  165           int size = original.count;
  166           char[] originalValue = original.value;
  167           char[] v;
  168           if (originalValue.length > size) {
  169               // The array representing the String is bigger than the new
  170               // String itself.  Perhaps this constructor is being called
  171               // in order to trim the baggage, so make a copy of the array.
  172               int off = original.offset;
  173               v = Arrays.copyOfRange(originalValue, off, off+size);
  174           } else {
  175               // The array representing the String is the same
  176               // size as the String, so no point in making a copy.
  177               v = originalValue;
  178           }
  179           this.offset = 0;
  180           this.count = size;
  181           this.value = v;

C'est une chose que beaucoup de développeurs oublient et qui est importante car une petite chaîne de caractères peut empêcher le gaspillage d'un tableau de caractères plus grand. Voir cette question connexe où j'ai déjà souligné ce point : Java ne récupère pas la mémoire . De nombreux développeurs estiment que la décision des concepteurs de Java d'utiliser cette vieille astuce d'optimisation familière aux codeurs C a, en fait, fait plus de mal que de bien. Beaucoup d'entre nous le savent parce que nous en avons fait les frais et que nous avons dû consulter le code source de Sun pour comprendre ce qui s'est passé...

Comme le souligne Marko (voir les commentaires ci-dessous), dans OpenJDK, à partir de java 7 Update 6, substring ne partage plus le tableau de chars et la fonction String(String) est donc inutile. Mais c'est toujours rapide (même plus rapide en fait) et comme ce changement n'a pas été propagé à toutes les VM (et probablement pas à tous vos clients), je recommanderais de garder cette meilleure pratique pour utiliser new String(substring) alors que l'ancien comportement le justifiait.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X