15 février 2008

Différences entre String, StringBuffer et StringBuilder

Pour un développeur Java confirmé les différences sont évidente en revanche pour un développeur Java junior, c'est n'est pas évident. Voilà donc une petite explication rapide.

Un objet de type String est un objet non mutable tandis qu'un objet de type StringBuffer et StringBuilder est mutable (sa valeur peut changer au cours du temps).

La seule différence qui existe entre un objet de type StringBuffer et StringBuilder est qu'un objet de type StringBuilder n'est pas synchronisé alors que StringBuffer est synchronisé. Il en résulte donc qu'une application qui n'a pas le besoin d'un environnement multi-threadé peut utiliser StringBuilder pour avoir de meilleure performance. En effet StringBuilder est plus efficace que StringBuffer.

Notez que StringBuilder a été introduit à partir du JDK5.0, donc si vous êtes en JDK inférieur, vous ne pouvez pas utiliser cette classe.

Critère de sélection entre String, StringBuffer et StringBuilder:

  1. Si votre chaine de caractères ne va pas changer, utilisez la classe String parce qu'un objet de type String est un objet non mutable.
  2. Si votre chaine de caractères va changer et est accédée par un seul thread, utilisez StringBuilder parce que StringBuilder n'est pas synchronisé et sera donc plus rapide que StringBuffer.
  3. Si votre chaine de caractères va changer et est accédée par plusieurs threads, utilisez StringBuffer parce que StringBuffer est synchronisé.
Pour plus d'informations sur ces 3 classes, reportez-vous à la javadoc du JDK pour chacune des classes.

10 Comments:

Anonyme said...

Merci beaucoup =)

Stéphanie

Anonyme said...

Merci pour ton explication simple et claire :-)

Anonyme said...

Merci - Mais il manque des exemples - La différence est pas tout a fait claire. Lorsque vous dite : "Si votre chaine de caractères ne va pas changer ..." - qu'est ce que tu veux dire par ne va changer ( en taille ? ) si c'est bien en taille , alors comment se comporte String ? et comment se comporte StringBuffer ?.

Ludovic BERT said...

Je vous conseil de lire bien en détail la Javadoc.

Il faut savoir qu'un objet String n'est pas mutable. Ce qui signifie que sa valeur ne peux jamais changer. Par exemple: si s = "test" et s2 = s.toUpperCase() alors s sera toujours égal à "test" et conservera la même référence Java. s2 sera égal à "TEST" et sera une nouvelle référence Java (un autre objet string sera crée). En d'autres termes, cela signifique que les 2 variables pointerons sur 2 objets différents. Un autre exemple identique est aussi valible avec s2 = s.concat("_").

En revanche StringBuffer et StringBuilder sont mutable et leur valeur peut donc changer. Reprenons le même exemple: si stringBuffer = new StringBuffer("test") et stringBuffer2 = stringBuffer.append("_") alors stringBuffer sera égal à "test_" et stringBuffer2 sera égal à "test_". Mais ce n'est pas tout la référence Java de stringBuffer et stringBuffer2 seront les même ce qui signifie que les 2 variables pointerons sur le même objet.

Voilà, j'espère que c'est un peu plus clair.

Anonyme said...

Merci infiniment
Asmaâ

Anonyme said...

Simple, clair, efficace : Merci

Anonyme said...

Salut !
il y a un cas dont vous n'avez pas parlez !, jetez un coup d’œil sur cet exemple :
String s = "Toto";
s = s.concat(" !! ");
Ici la valeur de la chaine de caractère s est à été changée de "Toto" vers "Toto !!", Donc il y a un changement au niveau de la longueur de la chaine s.
Comment ça se fait alors que la chaine est mutable !?!

Des idées s'il vous plait.

Ludovic BERT said...

Bonjour,

Je vous invite à lire la javadoc en détails car il est bien dit que java.lang.String est immutable, ainsi que la description de méthode concat, qui retroune une nouvelle chaîne de caractère qui est la concaténation résultante.

Donc si l'on regarde votre exemple: s.concat() return non pas la même référence Java sur l'objet, la référence manipulée par s est une autre référence que celle qui était initialement accessible par la variable s.

Dans votre cas, il y a création de 2 objets java.lang.String:
- "Toto"
- "Toto !! "
et seul la référence sur "Toto !! " est conservée.

J'espère que cela vous éclairera.

Anonyme said...

Ok, c'est claire.
Je me demande cette fois ci, puisque dans mon exemple j'ai crée deux objets, le premier objet "Toto" est ce qu'il sera libéré de la mémoire ?

Ludovic BERT said...

Oui, il sera éligible par le GC puisqu'il n'y aura plus de strong référence sur cet objet.

Par contre si ce genre de comportement est utilisé dans des itérations, il vaut mieux utiliser un StringBuffer ou un StringBuilder (en fonction du besoin) cela permet d'éviter de créer des objets temporaires et inutiles en mémoire, en plus cela peut créer un overhead CPU inutile puisque les objets devront être supprimer de la heap lors de GC.