Vous êtes sur la page 1sur 15

Institut Supérieur des Science Appliquées Année universitaire : 2019-2020

Et de Technologie de Sousse

Matière : Programmation Orientée Objet 2 (Java) Enseignant : Dr. Majd BELLAAJ

Filière : Deuxième Année Cycle Préparatoire

TD 8
I. LA CLASSE STRING

 Dans cette section, on traite l'utilisation de la classe java.lang.String.


 La chaîne contenue par un objet String ne peut pas être modifiée. Si on veut traiter de
chaînes de caractères modifiables, on peut utiliser la classe java.lang.StringBuffer.
Aucun exemple n'est donné ici sur la classe StringBuffer.
 Lorsque le compilateur rencontre une série de caractères entre doubles apostrophes, il
crée automatiquement un objet String, sauf si cette chaîne a déjà été rencontrée, auquel
cas un même objet String peut servir pour les deux chaînes.

Le langage définit par ailleurs un opérateur capable de travailler avec des objets String,
l'opérateur + de concaténation.

1. Création et utilisation d'objets de la classe String


2. Quelques méthodes de la classe String

Concaténation

Si dans un programme Java, l'un des opérandes du signe + se trouve être une chaîne de
caractères (de type String), alors ce signe + est l'opérateur de concaténation. Si les deux
opérandes sont des chaînes de caractères, le résultat est la concaténation des chaînes de
caractères. Si l'un des opérandes n'est pas une chaîne de caractères, le langage java a prévu une
traduction de l'opérande qui n'est pas une chaîne de caractères en une chaîne de caractères
représentant celui-ci.

1
1. Création et utilisation d'objets de la classe String

 Cet exemple reprend de l'opérateur + et de la méthode toString. Il introduit aussi un


procédé fondamental en Java : la surcharge.
public class EcritChaine {
String chaine = 3 + " curieux";
void ecrire() {
System.out.println(chaine +" a pour longueur " + chaine.length()); }
void ecrire(String s) {
System.out.println(chaine + s); }
}
class EssaiEcritChaine {
public static void main(String[] arg) {
EcritChaine ecrivain = new EcritChaine();
ecrivain.ecrire();
ecrivain.ecrire(" se rencontrent"); }
}

 On obtient à l'exécution du programme écrit dans la classe EssaiEcritChaine :

3 curieux a pour longueur 9


3 curieux se rencontrent

String chaine = 3 + " curieux"; : un des opérandes du signes + est une chaîne de caractères,
l'opérateur + est donc ici l'opérateur de concaténation ; l'int 3 est traduit en une chaîne de caractères
avant d'être concaténé avec " curieux" ; le résultat est une chaîne de caractères, c'est-à-dire en Java un
objet de type String.

chaine.length() : la méthode length() de la classe String retourne le nombre de caractères d'une


chaîne.

void ecrire(String s) : on a déjà défini une méthode ecrire() dans la classe EcritChaine ; on utilise ici
le principe de la surcharge. Il n'y aura pas confusion entre les méthodes ecrire car elles diffèrent par le
jeu de leurs paramètres.

2
2. Quelques méthodes de la classe String

 Cet exemple illustre principalement les méthodes equals et compareTo, méthodes


d'instance définies dans la classe String.

class MethodeChaine {

public static void main(String[] arg) {

String r = "essai";

String s = "es" + "sai";

String t = "ESSAI".toLowerCase();

String u = "est";

System.out.println("r == s vaut : " + (r == s));

System.out.println("r == t vaut : " + (r == t));

System.out.println("r.equals(t) vaut : " + r.equals(t));

System.out.println("r.compareTo(t) vaut : " + r.compareTo(t));

System.out.println("r.compareTo(u) vaut : " + r.compareTo(u));

System.out.println("u.compareTo(r) vaut : " + u.compareTo(r)); }


}

 On obtient à l'exécution :

r == s vaut : true
r == u vaut : false
r.equals(t) vaut : true
r.compareTo(t) vaut : 0
r.compareTo(u) vaut : -1
u.compareTo(r) vaut : 1

String t = "ESSAI".toLowerCase(); : la méthode toLowerCase est une méthode d'instance de la


classe String qui construit l'instance de la classe String obtenue en changeant toutes les lettres de la
chaîne de caractères concernée (ici : "ESSAI") en la même chaîne mais écrite toute en minuscules.
Après cette instruction, t contient donc la chaîne "essai".

3
r == s : la valeur de cette expression, true, montre que les références r et s sont ici égales ; cela est
ainsi car une seule instance de la classe String a été créée pour les deux chaînes de caractères, qui ont
été repérées comme identiques. Il est néanmoins beaucoup plus sûr d'utiliser la méthode equals pour
tester l'égalité de deux chaînes de caractères. Voyez le cas suivant.

r == t : cette expression vaut false ; les variables r et t référencent pourtant deux instances différentes
de la classe String qui contiennent la même chaîne de caractères.

r.equals(t) : cette expression vaut true, ce qui est correct. D'une façon plus générale, il ne faut pas
tester directement, avec "==", l'égalité de deux chaînes de caractères, mais utiliser la
méthode equals comme ici, ou bien la méthode compareTo.

r.compareTo(u) : la méthode compareTo est une méthode d'instance de la classe String ; ici, la
méthode est appliquée à r, qu'on compare à l'objet de type String indiqué dans les parenthèses, c'est-à-
dire à u. La méthode retourne 0 si r et u sont identiques, -1 si r vient avant u dans l'ordre alphabétique,
et 1 si r vient après u.

Exercice 1
Un palindrome est un mot que l'on peut lire dans les deux sens. La distinction entre
majuscules/minuscules n'a aucune importance pour la lecture d'un palindrome. Si on ne tient
pas compte des espaces, des virgules, des tirets et des apostrophes (i.e. les caractères ' ', ',', '-
' et '\''), une phrase complète peut aussi être considérée comme un palindrome. Exemples de
palindromes:
Otto
Elu par cette crapule
Esope reste ici et se repose
Tu l'as trop ecrase, Cesar, ce Port-Salut
A man, a plan, a canal, Panama
Exemples de non-palindromes:
Cours de Java
Le pont de la rivière Kwai
Ecrivez un programme Palindrome.java qui lit une chaine de caractères du clavier et qui teste
s'il s'agit d'un palindrome.

4
Exemple d'exécution:
Entrez un mot ou une phrase : Otto
C'est un palindrome !
Pour ce programme, il convient d'utiliser plusieurs méthodes prédéfinies de la
classe String, comme par exemple charAt(), toLowerCase() et length().
 char charAt (int n) : fournit le n ième caractère de la chaîne de l’objet courant.

II. LES CLASSES INTERNES

Une classe en Java peut être insérée dans une autre classe. Ci-dessous, B est une classe
interne à la classe A. Un objet d’une classe interne est associé à l’objet de la classe englobant
l’ayant créé. Un objet interne peut accéder aux attributs et méthodes de l’objet externe associé.
Un objet externe peut accéder aux champs et méthodes de l’objet qu’il a créé.

public class A {
attributs de A // par exemple B b1 = new B() ; B b2 = new B() ;
méthodes de A // les méthodes d’instance (non static) peuvent créer et utiliser des objets de la
classe B
class B {
// classe interne : aucun objet de type B n’est a priori créé lorsqu’on crée un objet de type A.
// un objet de classe B peut être créé dans une méthode de A ou en tant qu’attribut de A.
attributs d’instance de B
méthodes d’instance de B // elles peuvent accéder aux attributs et méthodes de A.
} // class B
} // class A

 Exemple de programme Java :

// A.java
public class A {
int va = 10;
String mot = "bonjour";
B nb = new B(); // objet B (classe interne) attribut de la classe A

A (int va) {
this.va = va;
}

void a1 () {

5
System.out.println ("\n\na1 : creation de objetb1");
B objetb1 = new B(100); // objet de la classe interne.
System.out.println ("a1 : objetb1.vb : " + objetb1.vb); // accès à l’attribut (vb) de objet b1 de la
//classe interne B.
objetb1.b1(); // appel d’une méthode de la classe B.
System.out.println ("\n\na1 : creation de objetb2");
B objetb2 = new B(); // objet de la classe interne
System.out.println ("a1 : objetb2.vb : " + objetb2.vb); // accès à l’attribut (vb) de objetb2 de la
//classe interne B
System.out.println ("*** objet B : objetb2 "+objetb2);
objetb2.b1(); // appel d’une méthode de la classe B
} // a1

void a2 () {
System.out.println ("*** methode a2 ");
} //a2

// classe interne B
public class B {
private int vb = 5; // attribut de la classe interne
B (int vb) {
this.vb = vb;
}
B () {
System.out.println ("*** objet B attribut de la classe A : "+nb);
System.out.println ();
}
void b1 () {
System.out.println (" b1 : mot " + mot + ", va "+ va + ", vb " + vb); // un objet de la classe B
peut accéder à un attribut de A (ex : accès a l’attribut "va" de la classe A)
a2(); // appel d’une méthode de la classe A
}
} // fin de la classe interne B

public static void main (String[] args) {


System.out.println ("\n\ncreation de objeta1");
A objeta1 = new A(10);
objeta1.a1();
System.out.println();
System.out.println ("\n\ncreation de objeta2");
A objeta2 = new A(50);
objeta2.a1();
System.out.println();
System.out.println("nb:"+objeta2.nb);

6
System.out.println("va:"+objeta2.va);
System.out.println("mot:"+objeta2.mot);} // main
} // fin de class A

Résultats d'exécution :

creation de objet a1
*** objet B attribut de la classe A : null

a1 : creation d'objetb1
a1 : objetb1.vb : 100
b1 : mot bonjour, va 10, vb 100
*** methode a2

a1 : creation d'objetb2
*** objet B attribut de la classe A : ClasseInterne_.A$B@15db9742

a1 : objetb2.vb : 5
*** objet B : objetb2 ClasseInterne_.A$B@6d06d69c
b1 : mot bonjour, va 10, vb 5
*** methode a2

creation de objet a2
*** objet B attribut de la classe A : null

a1 : creation d'objetb1
a1 : objetb1.vb : 100
b1 : mot bonjour, va 50, vb 100
*** methode a2

a1 : creation d'objetb2
*** objet B attribut de la classe A : ClasseInterne_.A$B@7852e922

7
a1 : objetb2.vb : 5
*** objet B : objetb2 ClasseInterne_.A$B@4e25154f
b1 : mot bonjour, va 50, vb 5
*** methode a2

nb:ClasseInterne_.A$B@7852e922
va:50
mot:bonjour

III. LES TYPES ENUMERES

 Un type énuméré permet de définir un ensemble d'identificateurs pour des constantes ;


il peut permettre par exemple de définir l'ensemble : LUNDI, MARDI, ... pour les
jours de la semaine. A partir du JDK 5.0, on peut définir des types énumérés à l'aide
de classes. Ces classes diffèrent des classes traditionnelles ; en particulier, leur en-tête
commence par le mot enum à la place du mot class. Nous donnons deux exemples. Le
premier est suffisant pour un usage simple d'un type énuméré et le second permet de
mieux comprendre ce type et ses possibilités.

Premier exemple

 La classe Jour du premier exemple consiste uniquement en une énumération


d'identificateurs pour les jours de la semaine. Cette énumération doit nécessairement
être en première ligne (sauf d'éventuels commentaires) de la définition de la classe.
Une méthode main utilise la classe Jour ; on y utilise une instruction par cas selon les
jours de la semaine.

public enum Jour {


LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE;}

class EssaiJour {
public static void main(String[] arg) {
Jour jour = Jour. LUNDI; // Jour jour = Jour.valueOf(arg[0]);
if (jour == Jour.SAMEDI)
System.out.print("fin de semaine : ");
switch(jour) {
case SAMEDI :
case DIMANCHE :
System.out.println("se reposer");
break;
default :

8
System.out.println("travailler");
break; }
}
}
Résultat d'exécution:
travailler

 Les classes pour les types énumérés étendent toujours la classe java.lang.Enum, sans
que cela figure explicitement. En conséquence, puisque Java ne permet pas l'héritage
multiple, une telle classe ne peut pas étendre une autre classe. Les éléments énumérés
ne sont rien d'autres que des instances de la classe enum concernée ; il n'est pas possible
de construire ultérieurement d'autres instances que celles énumérées immédiatement
dans la définition. On peut définir un constructeur comme dans l'exemple ci-dessous.
La classe java.lang.Enum possède des méthodes dont héritent les types énumérés ; en
particulier, la méthode toString renvoie le nom de l'item.

Second exemple

 Le second exemple propose plus de possibilités. On définit enum JourPlus. On y


énumère encore les jours de la semaine. Un constructeur permet d'associer à un jour de
la semaine une valeur (un nombre d'heures de travail) ; on ajoute une méthode, la
méthode action, qui peut s'appliquer à toute instance de type JourPlus.

public enum JourPlus {


LUNDI(8), MARDI(8), MERCREDI(8), JEUDI(8), VENDREDI(8), SAMEDI(0),
DIMANCHE(0);
private int nbHeures;

JourPlus(int nb) {
nbHeures = nb; }

public int getNbHeures() {


return nbHeures; }

public String action() {

9
switch(this) {
case SAMEDI : return " se reposer";
case DIMANCHE : return "sport et loisir";
default : return "travailler"; }
}
}

class EssaiJourPlus {
public static void main(String[] arg) {
JourPlus unJour = JourPlus.SAMEDI; //Jour jour = Jour.valueOf(arg[0]);
System.out.println("numero de " + unJour + " : " + unJour.ordinal());
System.out.println();
System.out.println(unJour + " : " + unJour.action());
System.out.println();

for (JourPlus jour : JourPlus.values())


System.out.println("nombre d'heures de " + jour + " : " +
jour.getNbHeures()); }
}
 Résultat d'exécution
numero de SAMEDI : 5
SAMEDI : se reposer
nombre d'heures de LUNDI : 8
nombre d'heures de MARDI : 8
nombre d'heures de MERCREDI : 8
nombre d'heures de JEUDI : 8
nombre d'heures de VENDREDI : 8
nombre d'heures de SAMEDI : 0
nombre d'heures de DIMANCHE : 0

public enum Jour : il s'agit de l'en-tête de la classe ; le mot réservé enum est obligatoire et Jour est le
nom du type énuméré.

LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE; : il s'agit de


l'énumération des constantes.

10
Jour.valueOf(arg[0]) : renvoie l'objet de l'énumération dont le nom est donné en argument sous
forme d'une chaîne de caractères.

jour == Jour.SAMEDI : SAMEDI s'utilise comme une constante statique de type Jour ; d'autre part,
on peut toujours comparer comme ici des valeurs de types énumérés avec == sans faire appel à la
méthode equals.

switch(jour) : l'instruction switch est possible avec un type énuméré, comme le montre l'exemple.

SAMEDI : dans l'instruction switch , les items de type Jour sont obligatoirement indiqués directement,
sans mettre par exemple Jour.SAMEDI.

public JourPlus(int nb) : on peut définir un constructeur. Lorsqu'on déclare la liste énumérée, on doit
alors mettre des arguments destinés au(x) constructeur(s), comme on le voit sur l'exemple.

public String action() : on peut définir des méthodes( statiques ou d'instance).

unJour.ordinal() : la méthode ordinal est une méthode définie dans la classe java.lang.Enum et qui
renvoie le numéro d'ordre dans l'énumération, en commençant à la valeur 0.

for (JourPlus jour : JourPlus.values()) : on remarque ici une façon de définir la boucle for pour un
type énuméré ; la variable jour prend successivement toutes les valeurs énumérées dans le
type JourPlus.

11
IV. LA CLASSE SCANNER

Pour la lecture de valeurs au clavier, utilisez la classe Scanner du package standard


java.util (version JDK 1.5 et supérieur).
Dans l'exemple suivant, vous trouverez un exemple d'utilisation de cette classe pour lire des
données au clavier.

ScannerDemo.java

/* programme de démonstration de la classe Scanner qui fournit des méthodes de lecture
au clavier simples pour les types de données de base les plus courants.

*/

import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.print("entrez une chaine de caractères : ");
String s = sc.next();
System.out.println("chaine lue : " + s);

System.out.print("entrez un entier : ");


int i = sc.nextInt();
System.out.println("entier lu : " + i);

System.out.print("entrez un réel (float) : ");


float f = sc.nextFloat();
System.out.println("réel (float) lu : " + f);

System.out.print("entrez une réel (double) : ");


double d = sc.nextDouble();
System.out.println("réel (double) lu : " + d);

System.out.print("entrez un booléen : ");

12
boolean b = sc.nextBoolean();
System.out.println("booleen lu : " + b);

System.out.print("entrez deux coordonnées x et y séparées par un espace : ");


float x = sc.nextFloat();
float y = sc.nextFloat();
System.out.println("x : " + x + " y : " + y);
}
}
Pour la liste complète des méthodes exposées par la classe java.util.Scanner, consultez le
lien suivant https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html.

IV. LA RÉCURSIVITÉ
Le langage Java comme C ou C++ gère la récursivité des fonctions. Une fonction peut
s’appeler elle-même pour opérer sur de nouveaux paramètres. La fonction doit comporter un
test d’arrêt (des appels récursifs) qu’il est conseillé de mettre en début de fonction.
Les boucles récursives
Une boucle peut aussi s’écrire sous forme récursive. On recommence (appel récursif) le
corps de la boucle tant qu’on n’a pas atteint la valeur limite de sortie de la boucle. La boucle
est croissante ou décroissante suivant que l’écriture (l’action de la boucle) est faite avant ou
après l’appel récursif.
// BouclesRecursives.java
class BouclesRecursives {
static void boucleDecroissante (int n) {
if (n > 0) {
System.out.println ("boucleDecroissante valeur de n : " + n);
boucleDecroissante (n-1);
}
}
static void boucleCroissante (int n) {
if (n > 0) {
boucleCroissante (n-1);
System.out.println ("boucleCroissante valeur de n : " + n);
}
}
public static void main (String[] args) {
boucleDecroissante (5);

13
System.out.println ("\n");
boucleCroissante (5);
}
} // class BouclesRecursives
Résultats d’exécution :
boucleDecroissante valeur de n : 5
boucleDecroissante valeur de n : 4
boucleDecroissante valeur de n : 3
boucleDecroissante valeur de n : 2
boucleDecroissante valeur de n : 1

boucleCroissante valeur de n : 1
boucleCroissante valeur de n : 2
boucleCroissante valeur de n : 3
boucleCroissante valeur de n : 4
boucleCroissante valeur de n : 5

Exercice 2
Ecrivez un programme Java qui calcul le factorielle de n : "Calcul récursif et itératif de la
factorielle de n".
Pour calculer n! (factorielle n), on peut utiliser deux formules différentes :
1- La formule itérative :
n! = 1 * 2 * 3 * ... * n
2- La formule récursive définissant n! en fonction de (n-1)! :

0! (factorielle de zéro) = 1
pour tout entier n>0, n! = n * (n-1)!

 Dans le fichier Factorielle.java, définissez deux méthodes :


factorielleRecursive et factorielleIterative implémentant les deux méthodes de calcul
décrites précédemment. Le calcul devra se faire sur des entiers compris entre 0 et 12
introduits par l'utilisateur. Une méthode demanderNombre redemandera le nombre à
l'utilisateur tant que celui-ci ne sera pas compris dans l'intervalle souhaité.
 Implémentez ensuite la méthode main qui demandera un nombre à l'utilisateur et
calculera la factorielle de ce nombre des deux manières possibles.
 Pour terminer, ajouter une boucle demandant à l'utilisateur s'il souhaite recommencer.

14
Exemple de déroulement

Entrez un nombre entier compris entre 0 et 12 : 12


Méthode itérative :
12! = 479001600
Méthode récursive :
12! = 479001600
Voulez-vous recommencer [o/n] ? o
Entrez un nombre entier compris entre 0 et 12 : 6
Méthode itérative :
6! = 720
Méthode récursive :
6! = 720
Voulez-vous recommencer [o/n] ? n

15