Les chaînes String
La classe String
Le type de données String (chaîne de caractère) n'est pas un type élémentaire en Java, c'est une
classe. Donc une chaîne de type String est un objet qui n'est utilisable qu'à travers les méthodes
de la classe String.
Pour accéder à la classe String et à toutes ses méthodes, vous devez mettre avant la déclaration
de votre classe l'instruction d'importation de package suivante :
import [Link] ;
Un littéral de chaîne est une suite de caractères entre guillemets : " abcdef " est un exemple de
littéral de String.
Etant donné que cette classe est très utilisée les variables de type String bénéficient d'un statut
d'utilisation aussi souple que celui des autres types élémentaires. On peut les considérer comme
des listes de caractères numérotés de 0 à n-1 (si n figure le nombre de caractères de la chaîne).
Déclaration d'une variable String String str1;
Déclaration d'une variable String avec String str1 = " abcdef ";
initialisation
Ou
String str1 = new String("abcdef ");
On accède à la longueur d'une chaîne par la String str1 = "abcdef";
méthode : int longueur;
longueur = [Link]( ); // ici longueur vaut 5
int length( )
Toutefois les String de Java sont moins conviviales en utilisation que les string de pascal ou
celles de C#, il appartient au programmeur d'écrire lui-même ses méthodes d'insertion,
modification et suppression.
Toutes les autres manipulations sur des objets String nécessitent l'emploi de méthodes de la
classe String. Nous donnons quelques exemples d'utilisation de méthode classique sur les String.
Le type String possède des méthodes classiques d'extraction, de concaténation, de changement
de casse, etc.
Concaténation de deux chaînes String str1,str2,str3;
str1="bon";
Un opérateur ou une méthode str2="jour";
str3=str1+str2;
Opérateur : + sur les chaînes
ou
Méthode : String concat(String s)
Les deux écritures ci-dessous sont donc
équivalentes en Java :
str3 = str1+str2 str3 = [Link](str2)
On accède à un caractère de rang fixé d'une String ch1 = "abcdefghijk";
chaîne par la méthode :
char charAt(int rang)
Il est possible d'accéder en lecture seulement à
chaque caractère d'une chaîne, mais qu'il est
impossible de modifier un caractère
directement dans une chaîne. char car = [Link](4);
// ici la variable car contient la lettre 'e'
position d'une sous-chaîne à l'intérieur String ch1 = " abcdef " , ssch="cde";
d'une chaîne donnée :
méthode :
int indexOf ( String ssch)
int rang ;
rang = [Link] ( ssch );
// ici la variable rang vaut 2
Les String Java ne peuvent pas être considérées comme des tableaux de caractères, il est
nécessaire, si l'on souhaite se servir d'une String, d’utiliser la méthode toCharArray
pour convertir la chaîne en un tableau de caractères contenant tous les caractères de la
chaîne.
Enfin, attention ces méthodes de manipulation d'une chaîne ne modifient pas la chaîne objet qui
invoque la méthode mais renvoient un autre objet de chaîne différent. Ce nouvel objet est obtenu
après action de la méthode sur l'objet initial.
Soient les quatre lignes de programme suivantes :
String str1 = "abcdef" ;
char [ ] tCarac ;
tCarac = [Link]( ) ;
tCarac = "abcdefghijk".toCharArray( );
Illustrons ci-dessous ce qui se passe relativement aux objets créés :
String str1 = "abcdef" ;
str1 référence un objet de chaîne.
char [ ] tCarac ;
tCarac = [Link]( ) ;
tCarac référence un objet de tableau à 6
éléments.
tCarac = "abcdefghijk".toCharArray( );
tCarac référence maintenant un nouvel objet de
tableau à 11 éléments, l'objet précédent est
perdu (éligible au Garbage collector)
L'exemple précédent sur la concaténation ne permet pas de voir que l'opérateur + ou la méthode
concat renvoie réellement un nouvel objet en particulier lors de l'écriture des quatre lignes
suivantes :
String str1,str2;
str1="bon";
str2="jour";
str1=str1+str2;
Illustrons ici aussi ce qui se passe relativement aux objets créés :
String str1,str2;
str1="bon";
str2="jour";
str1=str1+str2;
un nouvel objet de chaîne a été créé et str1
"pointe" maintenant vers lui.
Opérateurs d'égalité de String
L'opérateur d'égalité = = , détermine si deux objets String spécifiés ont la même référence et
non la même valeur, il ne se comporte pas en Java comme sur des éléments de type de base
(int, char,...)
String a , b ;
(a = = b ) renvoie true si les variables a et b référencent chacune le même objet de chaîne
sinon il renvoie false.
La méthode boolean equals(Object s) teste si deux chaînes n'ayant pas la même référence
ont la même valeur.
String a , b ;
[Link] ( b ) renvoie true si les variables a et b ont la même valeur sinon il renvoie false.
En d'autres termes si nous avons deux variables de String ch1 et ch2, que nous ayons écrit ch1 =
"abcdef"; et plus loin ch2 = "abcdef"; les variables ch1 et ch2 n'ont pas la même référence mais
ont la même valeur (valeur = "abcdef").
Voici un morceau de programme qui permet de tester l'opérateur d'égalité = = et la méthode
equals :
String s1,s2,s3,ch;
ch = "abcdef";
s1 = ch;
s2 = "abcdef";
s3 = new String("abcdef".toCharArray( ));
[Link]("s1="+s1);
[Link] ("s2="+s2);
[Link] ("s3="+s3);
[Link] ("ch="+ch);
if( s1 == ch ) [Link] ("s1=ch");
else [Link] ("s1<>ch");
if( s1 == s3 ) [Link] ("s1=s3");
else [Link] ("s1<>s3");
if( [Link](s2) ) [Link] ("s1 même val. que s2");
else [Link] ("s1 différent de s2");
if( [Link](s3) ) [Link] ("s1 même val. que s3");
else [Link] ("s1 différent de s3");
if( [Link](ch) ) [Link] ("s1 même val. que ch");
else [Link] ("s1 différent de ch");
Après exécution on obtient :
ATTENTION
En fait, Java a un problème de cohérence avec les littéraux de String. Le morceau de programme
ci-dessous montre cinq évaluations équivalentes de la String s2 qui contient après l'affectation la
chaîne "abcdef", puis deux tests d'égalité utilisant l'opérateur = = . Nous avons mis en
commentaire, après chacune des cinq affectations, le résultat des deux tests :
String ch;
ch = "abcdef" ;
String s2,s4="abc" ;
s2 = [Link]("def") ; /* après tests : s2<>abcdef, s2<>ch */
s2 = "abc".concat("def"); /* après tests : s2<>abcdef, s2<>ch */
s2 = s4+"def"; /* après tests : s2<>abcdef, s2<>ch */
s2="abc"+"def"; /* après tests : s2 ==abcdef, s2 == ch */
s2="abcdef"; /* après tests : s2 == abcdef, s2 == ch */
//-- tests d'égalité avec l'opérateur = =
if( s2 == "abcdef" ) [Link] ("s2==abcdef");
else [Link] ("s2<>abcdef");
if( s2 == ch ) [Link] ("s2==ch");
else [Link] ("s2<>ch");
Nous remarquons que selon que l'on utilise ou non des littéraux les résultats du test ne sont pas
les mêmes.
CONSEIL
Pour éviter des confusions et mémoriser des cas particuliers, il est conseillé d’utiliser la méthode
equals pour tester la valeur d'égalité de deux chaînes.
Rapport entre String et char
Une chaîne String contient des éléments de base de type char comment passe-t-on de l'un à
l'autre type.
1°) On ne peut pas considérer un char comme un cas particulier de String, le transtypage suivant
est refusé :
char car = 'r';
String s;
s = (String)car;
Il faut utiliser la méthode de conversion valueOf des String :
s = [Link](car);
2°) On peut concaténer avec l'opérateur +, des char à une chaîne String déjà existante et affecter
le résultat à une String :
String s1 , s2 ="abc" ;
char c = 'e' ;
s1 = s2 + 'd' ;
s1 = s2 + c ;
L'écriture suivante sera refusée : Ecriture correcte associée :
String s1 , s2 ="abc" ; String s1 , s2 ="abc" ;
char c = 'e' ; char c = 'e' ;
s1 = 'd' + c ; // types incompatibles s1 = "d" + [Link] (c) ;
s1 = 'd' + 'e'; // types incompatibles s1 = "d" + "e";
Le caractère 'e' est de type char,
La chaîne "e" est de type String (elle ne contient qu'un seul caractère)
Tableaux et matrices
Dès que l'on travaille avec de nombreuses données homogènes ( de même type) la première
structure de base permettant le regroupement de ces données est le tableau. Java comme tous les
langages algorithmiques propose cette structure au programmeur. Comme pour les String, pour
des raisons d'efficacité dans l'encombrement mémoire, les tableaux sont gérés par Java, comme
des objets.
Les tableaux Java sont comme en Delphi, des tableaux de tous types y compris des types
objets.
Il n'y a pas de mot clef spécifique pour la classe tableaux, mais l'opérateur symbolique [ ]
indique qu'une variable de type fixé est un tableau.
La taille d'un tableau doit obligatoirement avoir été définie avant que Java accepte que
vous l'utilisiez !
Les tableaux à une dimension
Déclaration d'une variable de tableau :
int [ ] table1;
char [ ] table2;
float [ ] table3;
...
String [ ] tableStr;
Déclaration d'une variable de tableau avec définition explicite de taille :
int [ ] table1 = new int [5];
char [] table2 = new char [12];
float [ ] table3 = new float [8];
...
String [ ] tableStr = new String [9];
Le mot clef new correspond à la création d'un nouvel objet (un nouveau tableau) dont la taille
est fixée par la valeur indiquée entre les crochets. Ici 4 tableaux sont créés et prêts à être utilisés :
table1 contiendra 5 entiers 32 bits, table2 contiendra 12 caractères, table3 contiendra 8 réels en
simple précision et tableStr contiendra 9 chaînes de type String.
On peut aussi déclarer un tableau sous la forme de deux instructions : une instruction de
déclaration et une instruction de définition de taille avec le mot clef new, la seconde pouvant être
mise n'importe où dans le corps d'instruction, mais elle doit être utilisée avant toute manipulation
du tableau. Cette dernière instruction de définition peut être répétée plusieurs fois dans le
programme, il s'agira alors à chaque fois de la création d'un nouvel objet (donc un nouveau
tableau), l'ancien étant détruit et désalloué automatiquement par le ramasse-miettes (garbage
collector) de Java.
int [ ] table1; char
[ ] table2; float [ ]
table3; String [ ]
tableStr;
....
table1 = new int [5];
table2 = new char [12];
table3 = new float [8];
tableStr = new String [9];
Déclaration et initialisation d'un tableau avec définition implicite de taille :
int [ ] table1 = {17,-9,4,3,57};
char [ ] table2 = {'a','j','k','m','z'};
float [ ] table3 = {-15.7f,75,-22.03f,3,57};
String [ ] tableStr = {"chat","chien","souris","rat","vache"};
Dans cette éventualité Java crée le tableau, calcule sa taille et l'initialise avec les valeurs
fournies.
Il existe un attribut général de la classe des tableaux, qui contient la taille
d'un tableau quelque soit son type, c'est l'attribut length.
Exemple :
int [ ] table1 = {17,-9,4,3,57};
int taille;
taille = [Link]; // taille = 5
Il existe des classes permettant de manipuler les tableaux :
La classe Array dans le package [Link], qui offre des méthodes de
classe permettant de créer dynamiquement et d'accéder dynamiquement à des tableaux.
La classe Arrays dans le package [Link], offre des méthodes de classe pour la
recherche et le tri d'éléments d'un tableau.
Utiliser un tableau
Un tableau en Java comme dans les autres langages algorithmiques, s'utilise à travers une cellule
de ce tableau repérée par un indice obligatoirement de type entier ou un char considéré comme
un entier (byte, short, int, long ou char).
Le premier élément d'un tableau est numéroté 0, le dernier length-1.
On peut ranger des valeurs ou des expressions du type général du tableau dans une cellule du
tableau.
Exemple avec un tableau de type int :
int [ ] table1 = new int [5];
// dans une instruction d'affectation:
table1[0] = -458;
table1[4] = 5891;
table1[5] = 72; <--- erreur de dépassement de la taille ! (valeur entre 0 et 4)
// dans une instruction de boucle:
for (int i = 0 ; i<= [Link]-1; i++)
table1[i] = 3*i-1; // après la boucle: table1 = {-1,2,5,8,11}
Même exemple avec un tableau de type char :
char [] table2 = new char [7];
table2[0] = '?' ;
table2[4] = 'a' ;
table2[14] = '#' ; <--- est une erreur de dépassement de la taille
for (int i = 0 ; i<= [Link]-1; i++)
table2[i] =(char)('a'+i);
//-- après la boucle: table2 = {'a', 'b', 'c' ,'d', 'e', 'f'}
Remarque :
Dans une classe exécutable la méthode main reçoit en paramètre un tableau de
String nommé args qui correspond en fait aux éventuels paramètres de
l'application elle-même:
public static void main(String [ ] args)
Les tableaux à deux dimension : matrices
Les tableaux en Java peuvent être à deux dimensions (voir même à plus de deux) auquel cas on
peut les appeler des matrices, ce sont aussi des objets et ils se comportent comme les tableaux à
une dimension tant au niveau des déclarations qu'au niveau des utilisations. La déclaration
s'effectue avec deux opérateurs crochets [ ] [ ] . Les matrices Java ne sont pas en réalité des
vraies matrices, elles ne sont qu'un cas particulier des tableaux multi indices.
Leur structuration n'est pas semblable à celle des tableaux pascal, en fait en java une matrice est
composée de plusieurs tableaux unidimensionnels de même taille (pour fixer les idées nous les
appellerons les lignes de la matrice) : dans une déclaration Java le premier crochet sert à indiquer
le nombre de lignes (nombre de tableaux à une dimension), le second crochet sert à indiquer la
taille de la ligne.
Un tel tableau à deux dimensions, peut être considéré comme un tableau unidimensionnel de
pointeurs, où chaque pointeur référence un autre tableau unidimensionnel.
Voici une manière imagée de visualiser une matrice à n+1 lignes et à p+1 colonnes
int [ ][ ] table = new int [n+1][p+1];
Les tableaux multiples en Java sont utilisables comme des tableaux unidimensionnels. Si l'on
garde bien présent à l'esprit le fait qu'une cellule contient une référence vers un autre tableau, on
peut alors écrire en Java soient des instructions pascal like comme table[i,j] traduite en java par
table[i][j], soient des instructions spécifiques à java n'ayant pas d'équivalent en pascal comme
dans l'exemple ci-après :
table[0] = new int[p+1];
table[1] = new int[p+1];
Dans chacune de ces deux instructions nous créons un
objet de tableau unidimensionnel qui est référencé par
la cellule de rang 0, puis par celle de rang 1.
Ou encore, en illustrant ce qui se passe après chaque instruction :
int [ ][ ] table = new int [n+1][p+1];
table[0] = new int[p+1];
int [ ] table1 = new int [p+1];
table[1] = table1 ;
Rien n'oblige les tableaux référencés d'avoir la même dimension, ce type de tableau se dénomme
tableaux en escalier ou tableaux déchiquetés en Java :
int [ ][ ] table = new int [3][ ];
table[0] = new int[2];
table[1] = new int[4];
table[2] = new int[3];
Si l'on souhaite réellement utiliser des matrices (dans lequel toutes les lignes ont la même
dimension) on emploiera l'écriture pascal-like, comme dans l'exemple qui suit.
Exemple d'écritures conseillées de matrice de type int :
int [ ][ ] table1 = new int [2][3];// deux lignes de dimension 3 chacune
// dans une instruction d'affectation:
table1[0][0] = -458;
table1[2][5] = -3; <--- est une erreur de dépassement ! (valeur entre 0 et 1)
table1[1][4] = 83; <--- est une erreur de dépassement ! (valeur entre 0 et 4)
// dans une instruction de boucle:
for (int i = 0 ; i<= 2; i++)
table1[1][i] = 3*i-1;
// dans une instruction de boucles imbriquées:
for (int i = 0 ; i<= 2; i++)
for (int k= 0 ; i<= 3; i++) table1[i][k] = 100;
Information sur la taille d'un tableau multi-indices :
Le même attribut général length de la classe des tableaux, contient la taille du tableau :
Exemple : matrice à deux lignes et à 3 colonnes
int [ ][ ] table1 = new int [2][3];
int taille;
taille = [Link]; // taille = 2 (nombre de lignes)
taille = table1[0].length; // taille = 3 (nombre de colonnes)
taille = table1[1].length; // taille = 3 (nombre de colonnes)
Java initialise les tableaux par défaut à 0 pour les int, byte, ... et à null pour les objets.