UKOnline

Classe String

Nous avons vu que pour utiliser des chaines de caractères en Java, il suffit simplement d'écrire la séquence de caractères entre guillemets doubles. Par exemple, pour afficher le texte Hello World ! à l'écran, on doit écrire l'instruction suivante :

Même si Java propose une forme littérale pour les chaines de caractères, il ne faut jamais oublier que ce sont des objets, il ne s'agit pas d'un type primitif. Si on voulait se passer de la forme littérale, il faudrait déclarer toutes les chaines de caractères comme une liste de caractères (type primitif char), ce qui est lourd et donc Java offre une forme littérale pour simplifier la vie du programmeur et rendre les programmes plus lisibles. Les chaines de caractères sont représentées par la classe String qui est le sujet de cette section.

Création d'un objet String

Pour créer une nouvelle chaine de caractères, on ne va pas utiliser new comme on l'a fait jusqu'à présent, on va simplement utiliser la forme littérale. On a déjà vu un autre cas où on crée des objets sans new à la section 4.6 sur l'auto boxing.

La variable s va donc contenir une référence vers un objet de type String. La figure 25 illustre ce qui se trouve en mémoire : il y a une variable de type objet dont le nom est s. Celle-ci contient une référence vers un objet de type String qui contient la chaine de caractères Hello World !.

Objet String
Un objet de type String.

Concaténation

La concaténation de deux chaines de caractères $A$ et $B$ est une nouvelle chaine $AB$. On a « collé » $B$ derrière $A$. Pour concaténer deux chaines de caractères, on peut soit faire appel à la méthode concat, soit utiliser l'opérateur de concaténation +, introduit en Java car on fait très souvent cette opération. On peut donc écrire :

Il est également possible de concaténer des données primitives avec des chaines de caractères. Les types primitifs seront convertis en chaines de caractères avant d'être concaténés. Pour être exact, ce seront des représentations des types primitifs sous forme de chaines de caractères qui seront concaténés.

L'exécution de cette instruction affiche à l'écran :

J'ai 18 ans.

Convertir un type primitif en String

Il est possible de convertir n'importe quel type primitif en une chaine de caractères en utilisant la méthode de classe valueOf de la classe String. Lorsqu'on fait une concaténation qui fait intervenir des types primitifs, c'est ce qui se passe de manière implicite; on aurait donc pu s'écrire :

Si on se rappelle qu'un appel vers une méthode qui renvoie une valeur est une expression et sachant que la méthode valueOf renvoie un objet de type String, on peut également écrire le tout en plus condensé :

On peut encore faire plus court si on fait un import statique de la méthode valueOf :

Convertir un objet en String

On vient de voir que pour convertir un type primitif en chaine de caractères, on utilise la méthode valueOf de la classe String. Pour convertir un objet en une chaine de caractères, plus précisément pour obtenir une représentation d'un objet sous forme de chaine de caractères, on utilise la méthode toString qui est applicable sur tous les objets. L'exemple suivant montre l'utilisation de cette méthode sur un objet de type Date :

En fait, lorsque vous utilisez System.out.print et System.out.println avec un objet en paramètre, la méthode toString est implicitement appelée. Par exemple, les deux instructions suivantes sont tout à fait équivalentes :

Priorité de l'opérateur de concaténation

Il y a deux opérateurs binaires + différents en Java. Le premier qu'on a vu dans le deuxième chapitre est l'opérateur d'addition. Dans cette section, on vient de voir qu'il s'agit également de l'opérateur de concaténation pour les chaines de caractères. C'est selon le type de ses opérandes qu'il s'agira soit de l'opérateur d'addition, soit de celui de concaténation.

Voici ce qui s'affichera à l'écran après exécution de ces instructions :

Concaténation : 1012.
Addition : 22.

Tout cela est bien normal, rappelez-vous la règle d'associativité qui intervient lorsqu'on a des opérateurs de même priorité : on évalue de gauche à droite. L'opérateur d'addition et celui de concaténation ayant la même priorité, une expression contenant les deux est évaluée de gauche à droite.

Pour la première instruction, la première opération est la concaténation de la chaine de caractères avec 10 puisqu'un des deux opérandes est de type String. Ensuite, le résultat sera concaténé avec 12 et enfin avec ".".

  "Concaténation : " + 10 + 12 + "."
= "Concaténation : 10" + 12 + "."
= "Concaténation : 1012" + "."
= "Concaténation : 1012."

Pour la seconde instruction, on force l'addition à se produire avant la concaténation grâce aux parenthèses. Comme les deux opérandes sont des nombres, il s'agit bien d'une addition et le résultat est différent :

  "Addition : " + (10 + 12) + "."
= "Addition : " + 22 + "."
= "Addition : 22" + "."
= "Addition : 22."

Séquence d'échappement

Comment fait-on pour afficher un guillemet double à l'écran ? Si on écrit System.out.println ("""), on sera face à une erreur de compilation. En effet, le guillemet double servant à marquer le début et la fin d'une chaine de caractères, le compilateur verra une chaine de caractères vide suivie d'un début de chaine non fermé.

Il y a cependant une solution à ce problème, déjà vue au premier chapitre, qui consiste à utiliser une séquence d'échappement. Pour rappel, une telle séquence commence par le caractère d'échappement, un backslash en Java ( \ ), que l'on fait suivre d'une suite de caractères qui sera traitées de manière spéciale par Java. Pour afficher un guillemet double à l'écran, on doit utiliser l'instruction suivante :

La séquence d'échappement utilisée pour insérer un guillemet double est donc \". Les différentes séquences d'échappements sont rappelées sur la figure 26, mais voyons avant tout un exemple qui en utilise plusieurs différents :

L'exécution de ce programme affiche à l'écran :

   Cher ami,

   Cela fait un moment qu'on ne s'est plus vu !
J'ai revu "bichette" hier.

Allez, à plus.
Séquence Signification
\b Backspace
\t Tabulation
\n Nouvelle ligne
\r Retour chariot
\" Guillemet double
\' Guillemet simple
\\ Backslash
Séquences d'échappement à utiliser dans les chaines de caractères.

Outre ces séquences d'échappement, il y avait également la séquence octale et la séquence unicode. Cette dernière est rappelée ci-dessous.

Représentation Unicode

Il y a encore une séquence d'échappement supplémentaire qui permet d'obtenir un caractère en connaissant son code. Rappelez-vous, tous les caractères sont associés à un entier dépendant de l'encodage utilisé. En ce qui concerne Java, il s'agit d'Unicode, et tous les caractères ont une valeur comprise entre 0 et 65 535. Par exemple, le caractère A correspond au code 65.

Pour insérer un caractère à partir de son code, on utilise la séquence d'échappement composée de \u suivi du numéro du caractère donné en hexadécimal sur quatre chiffres.

L'exécution du programme va simplement afficher :

La lettre A : A ;
le symbole marque déposée : © ;
l'idéogramme eau chinois : 水.

Comparaison de chaines de caractères

Pour comparer deux chaines de caractères, il faut bien entendu utiliser la méthode equals si on souhaite vérifier qu'elles possèdent exactement la même suite de caractères, puisqu'il s'agit d'objets. Si vous utilisez ==, ce seront les références qui seront comparées.

Il y a néanmoins une subtilité due à une optimisation que fait la machine virtuelle Java. Il n'y a qu'un seul objet qui est créé pour toutes les chaines de caractères qui sont des expressions constantes. Pour rappel, une telle expression est une dont la valeur peut-être calculée lors de la compilation. Prenons un exemple pour mieux comprendre :

L'exécution du programme affiche d'abord true true. En effet, les deux expressions "Hello" et "Hel" + "lo" sont toutes deux des expressions constantes qui représentent la même chaine de caractères. Il n'y a donc qu'un seul objet qui est créé en mémoire et les variables a et b contiennent donc la même référence.

L'exécution continue et affiche ensuite false true. En effet, les deux variables a et d contiennent des références vers des objets différents, mais représentant la même chaine de caractères. En effet, l'expression c + "lo" n'est pas une expression constante. Si la variable c avait été déclarée comme final, la valeur de a == d aurait été true.

La figure 27 montre la situation en mémoire après exécution de ces instructions. Les variables a et b référencent le même objet tandis que les variables c et d référencent chacune un objet différent. En réalité, on peut considérer que le code suivant a été produit par le compilateur, où chaque littéral de type String est stocké dans une constante :

String constant pool
Mémoire avec des objets de type String.

Instruction switch

Depuis Java 7, il est possible d'utiliser l'instruction switch vue au chapitre précédent avec des objets de type String pour autant que certaines conditions soient remplies. Voyons d'abord un exemple :

Dans cet exemple, on affecte une valeur à la variable fullWeekdayName en fonction de la valeur de la variable shortWeekdayName, toutes deux de type String. Tout comme on l'a déjà vu précédemment, les valeurs utilisées pour chaque case doivent être des expressions constantes. Les comparaisons faites par l'instruction switch sont faites avec la méthode equals, comparant donc les valeurs des chaines de caractères et non les références.

Enfin, sachez que le compilateur génère du code plus efficace lorsque vous utilisez l'instruction switch que lorsque vous faites une séquence de if-else if, lorsqu'il s'agit de l'utiliser avec des String.

Méthodes de la classe String

La classe String contient de nombreuses méthodes qui vous permettent de manipuler des chaines de caractères. Vous allez pouvoir parcourir les caractères d'une chaine, extraire une sous-chaine, concaténer plusieurs chaines, retrouver une sous-chaine, tester si une chaine commence ou se termine par une certaine chaine, etc. Toutes ces informations se retrouvent dans la documentation de l'API Standard Java et quelques méthodes sont reprises sur la figure 28.

Méthode Description
char charAt (int index) Renvoie le caractère en position index (le premier caractère est en position 0)
String concat (String str) Concatène l'objet cible avec str
boolean endsWith (String str) Teste si l'objet cible se termine par str
boolean equalsIgnoreCase (String str) Compare l'objet cible avec str sans tenir compte de la casse
int indexOf (String str) Renvoie la position de la première occurrence de str si l'objet cible contient la chaine str, sinon renvoie -1. Des variantes de cette méthode existent.
int length() Renvoie le nombre de caractères de l'objet cible
boolean startsWith (String str) Teste si l'objet cible commence par str
String substring (int begin, int end) Extrait la sous-chaine de l'objet cible compris entre les positions begin et end
String toLowerCase() Renvoie la chaine correspondant à l'objet cible dont toutes les lettres ont été changées en minuscules
String toUpperCase() Renvoie la chaine correspondant à l'objet cible dont toutes les lettres ont été changées en majuscules
Quelques méthodes de la classe String.