Vous êtes sur la page 1sur 52

1437-02-19

Cours Java

SMI & LP2I


Année -2015

k.afdel cours Java 1

k.afdel cours Java 2

1
1437-02-19

k.afdel cours Java 3

k.afdel cours Java 4

2
1437-02-19

k.afdel cours Java 5

k.afdel cours Java 6

3
1437-02-19

k.afdel cours Java 7

k.afdel cours Java 8

4
1437-02-19

k.afdel cours Java 9

k.afdel cours Java 10

5
1437-02-19

k.afdel cours Java 11

k.afdel cours Java 12

6
1437-02-19

k.afdel cours Java 13

k.afdel cours Java 14

7
1437-02-19

k.afdel cours Java 15

k.afdel cours Java 16

8
1437-02-19

k.afdel cours Java 17

k.afdel cours Java 18

9
1437-02-19

k.afdel cours Java 19

k.afdel cours Java 20

10
1437-02-19

k.afdel cours Java 21

k.afdel cours Java 22

11
1437-02-19

Les tableaux
• Un tableau est un ensemble indexé de données d'un même type. L'utilisation d'un
tableau se décompose en trois parties :
• Création du tableau
• Remplissage du tableau
• Lecture du tableau
Création d'un tableau
Un tableau se déclare et s'instancie comme une classe :
• int monTableau[ ] = new int[10];
• int [ ] monTableau = new int[10];
Si [ ] suit le type, toutes les variables déclarées seront des tableaux, alors que si [ ] suit le
nom de la variable, seule celle-ci est un tableau :
Exemple
• int [] premierTableau, deuxiemeTableau;
• float troisiemeTableau[], variable; // variable n'est pas un tableau.

Exemple : double[] myList = new double[10];

k.afdel cours Java 23

Remplissage d'un tableau


Une fois le tableau déclaré et instancié, nous pouvons le remplir :

• int [] monTableau = new int[10];


• monTableau[5] = 23;

L'indexation démarre à partir de 0, ce qui veut dire que, pour un tableau de N


éléments, la numérotation va de 0 à N-1.
Dans l'exemple ci-dessus, la 6ème case contient donc la valeur 23.

Nous pouvons également créer un tableau en énumérant son contenu :


• int [] monTableau = {5,8,6,0,7}; // Ce tableau contient 5 éléments.

Lorsque la variable est déjà déclarée, nous pouvons lui assigner d'autres
valeurs en utilisant l'opérateur new :
monTableau = new int[] {11,13,17,19,23,29};

k.afdel cours Java 24

12
1437-02-19

Lecture d'un tableau

• Lecture ou écriture des valeurs d'un tableau,

• int [] monTableau = {2,3,5,7,11,23,17}; //déclaration & initialisation d’un tableau


• int nb; // déclaration d’une variable
nb = monTableau[4];
System.out.println(« 6 elements du tableau est : »+ monTableau[5] ); // résultat 6 élément du tableau est :23

System.out.println(«nb = »+ nb ); // nb=11
Remarques

• L'indice 0 désigne le premier élément du tableau.


• L'attribut length d'un tableau donne sa longueur (le nombre d'éléments). Donc pour
un tableau nommé monTableau l'indice du dernier élément estmonTableau.length-1.
• Ceci est particulièrement utile lorsque nous voulons parcourir les éléments d'un
tableau.
float s=0.0;
for (int i = 0; i < monTableau.length; i++) {
s+= monTableau[i]; }
System.out.println(« La somme des éléments du tableau est : »+ s );

k.afdel cours Java 25

Les tableaux en Java


Java 5 fournit un moyen plus court de parcourir un tableau.
L'exemple suivant réalise le traitement sur monTableau :
for (int element : monTableau){
// traitement }
Exemple
public class TestTableau {
public static void main(String[] args)
{ double[] monTableau= {1.9, 2.9, 3.4, 3.5}; // Print all the array elements
float [] monTableaufloat= {1.9f, 2.9f, (float)3.4, 3.5f};
for (double element
element:: myList
myList))
{ System.out.println(element
System.out.println(element);
); } } }
Tableaux à plusieurs dimensions
En Java, les tableaux à plusieurs dimensions sont en fait des tableaux de tableaux.
tableaux
Exemple, pour allouer une matrice de 5 lignes de 6 colonnes :
int[][] matrice=new int[5][];
for (int i=0 ; i<matrice.length; i++) matrice[i]=new int[6];
int[][] matrice=new int[5][6]; // ici les ligne ont la même longueur qui est 5
La première version montre qu'il est possible de créer un tableau de tableaux
n'ayant pas forcément tous la même dimension.
k.afdel cours Java 26

13
1437-02-19

On peut également remplir le tableau à la déclaration et laisser le compilateur déterminer


les dimensions des tableaux, en imbriquant les accolades :
int[][] matrice =
{ { 0, 1, 4, 3 } , // ligne 0 c-à-d tableau [0] de int
{ 5, 7, 9, 11, 13, 15, 17 } // tableau [1] de int
};
Pour déterminer la longueur des tableaux, on utilise également l'attribut length :
• matrice.length // 2
• matrice[0].length // 4
• matrice[1].length // 7
De la même manière que précédemment, on peut facilement parcourir tous les éléments
du Matrice pour effectuer leurs somme :
int i, j;
Double s=0.0,
for(i=0; i<matrice.length; i++) {
for(j=0; j<matrice[i].length; j++) {
s+=matrice[i][j]
}
}
System.out.println(« La somme des éléments du Matrice est : »+ s );

k.afdel cours Java 27

Entrées et Sorties en Java

• Pour être utile, un programme doit entrer des données, produire les résultats
après traitement de ces données.
• Ce chapitre discute les entrées et les sorties des données provenant du
clavier et le moniteur.
• Il n'y a pas de déclarations standard dans la langue de Java pour les entrées
et sortie comme pour langage C/C++.
• Toutes les entrées entrés et sortie utilisent des méthodes faisant partie du
même paquet java.io.

• Flux d’entrée et sortie IO


• Avec Java, une source de données de l'entrée est appelée InputStream et
les données produites sont appelées OuputStream
OuputStream.

k.afdel cours Java 28

14
1437-02-19

• "O" est supposé représenter une donnée (chaîne de données) ordonné en fil
d’attente pour sortir ou pour entrer.
• En général, un programme peut avoir plusieurs flux d'entrés et produit
plusieurs flux de sortie. Pour la plupart des programmes possède trois flux
IO:
• System.in — flux d’entrée
• System.out — flux de sortie
• System.err — flux de sortie pour le message d’erreur.
• Normalement System.in est relié au clavier et les données sont de type
caractères. System.out et System.err les deux sont reliés au moniteur, et
aussi leurs données sont de type de caractères. Le paquet qui gère ces flux
est java.io
java.io.

k.afdel cours Java 29

Exemple
Les données envoie par le clavier à un programme sont de type caractère
incluant les caractères chiffres ‘0' jusqu’a ‘ 9.' Donc il faut convertir ces
caractères en données numériques pour être utilisées dans des opérations
arithmétiques.

import java.io.*;
class Echo{ public static void main (String[] args) throws IOException
{ InputStreamReader inStream = new InputStreamReader( System.in ) ;
BufferedReader stdin = new BufferedReader( inStream );
String inData;
System.out.println("Enter the data:");
inData = stdin.readLine();
System.out.println("You entered:" + inData );
}}
Note :
Utilise la notion d’IOException
IOException qui est nécessaire pour les programmes qui possèdent
un flux d’entrée.
Il informe le compilateur que le programme principal possède une flux d’entrée et qui
peut générer un erreur lors d’une opération de lecture des donnes à partir du clavier
si cela arrive le système informatique sera informé de l'échec et le programme
saura arrêté correctement.
correctement k.afdel cours Java 30

15
1437-02-19

BufferedReader

•L'opérateur new crée un objet BufferedReader hors du mémoire principale.


• L'objet BufferedReader peut être utilisé pour recevoir le flux en entée.
• "BufferedReader" paraît deux fois dans cette déclaration pour le premier:
1. "BufferedReader" décrit le type de la variable stdin (classe), pendant que le
2. deuxième crée l’objet avec new. L'objet BufferedReader utilise l'objet
InputStreamReader connecté à System.in.
• Cette connexion est effectuée une fois que l’objet BufferedReader est créé.

inData = stdin.readLine();
Le programme lit une ligne de données de type caractère provenant du clavier
en utilisant la méthode readLine qui fait partie de l'objet BufferedReader.

k.afdel cours Java 31

Saisie des Données Numériques


Integer Input :

import java.io.*;
class EchoSquare{
public static void main (String[] args) throws IOException
{ BufferedReader stdin = new BufferedReader (new InputStreamReader(System.in));
String inData;
int num, square; // declare two int variables
System.out.println("Enter an integer:");
inData = stdin.readLine();
num = Integer.parseInt
Integer.parseInt( inData ); // convert inData to int
square = num * num ; // compute the square
System.out.println("The square of " + inData + " is " + square);
}
}

k.afdel cours Java 32

16
1437-02-19

import java.io.*;
class StringToDouble{
public static void main (String[] args)
{ final String charData = "3.14159265";
double value;
value = Double.parseDouble( charData ) ;
System.out.println("value: " + value +" twice value: " + 2*value );
}}

Pour les autres Types de données

System.out.println("Saisie des nombres réelle");


inData3 = stdin.readLine();
NumFloat = Float.valueOf(inData3).floatValue();

System.out.println("Saisie des nombres carctère");
inData4 = stdin.readLine();
Numcar= inData4.charAt(0);
System.out.println("la caractere tapé est " +car);

System.out.println("Saisie des nombres long");


inData3 = stdin.readLine();
NumLong = Long.valueOf(inData3).longValue();
k.afdel cours Java 33

Entrées /Sorties
Utilisation de la class Scanner
Etape 1 importez la classe Scanner
import java.util.Scanner;
Etape 2 : saisir les données. Tous les entrées seront effectuées sous forme de chaine par java
Exemple
Scanner sc = new Scanner(System.in);
System.out.println("Veuillez saisir un mot :");
String str = sc.nextLine();
System.out.println("Vous avez saisi : " + str);
Ou saisie de caractère
System.out.println("Saisissez une lettre :");
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
char carac = str.charAt(0);
System.out.println("Vous avez saisi le caractère : " + carac);
Etape 3 : Conversion de la chaine en type de données primitives
Exemple :
Scanner sc = new Scanner(System.in);
int i = sc.nextInt(); System.out.println(" La valeur de i: " + i);
float f=sc.nexFloat(); System.out.println(" La valeur de f: " + f);
double d = sc.nextDouble(); System.out.println(" La valeur de d: " + d);
long l = sc.nextLong(); System.out.println(" La valeur de l: " + l);
byte b = sc.nextByte(); System.out.println(" La valeur de b: " + b);

k.afdel cours Java 34

17
1437-02-19

Programmation Orientée
Objet avec Java

k.afdel cours Java 35

Introduction
• La programmation orientée objet permet de concevoir une application
sous la forme d'un ensemble d'objets reliés entre eux par des relations
• Le programme orienté objet est pensé en terme d'objets abstraits inter
opérant entre eux alors que la programmation traditionnelle pense une
application en termes de fonctionnalités.
• L'une des caractéristiques de cette méthode permet de concevoir de
nouveaux objets à partir d'objets existants.
• Réutiliser les objets dans plusieurs applications. La réutilisation du code
fut un argument déterminant pour venter les avantages des langages à
objets.
• Nous allons découvrir les concepts de l'orienté objet implémentés par
java à savoir :
1. Objet et classe
2. Héritage
3. -Encapsulation (Accessibilité)
4. -Polymorphisme

k.afdel cours Java 36

18
1437-02-19

Objet, Classes

Objet
• Un objet est une structure informatique caractérisée par un état et un
ensemble d'opérations exécutables par cet objet qui caractérise son
comportement.
• Objet = état + comportement (opérations)
• Exemples:
• Objet Une Fenêtre :
– Etat : position, taille, bordure, titre, couleur,...
– Opérations: dessiner, déplacer. agrandir...
• Objet Un Fichier
– Etat : nom, directory, id, protections, propriétaire, contenu..
– Opérations : ouvrir, fermer, détruire,
• On regroupe un ensemble de caractéristiques communes aux objets sous la forme de
structures formelles, appelées classes
– Exemple de représentation graphique d'un objet (Notation UML) :

k.afdel cours Java 37

classe
• Une classe est un modèle de la structure statique (les champs ou attributs) et du
comportement dynamique (les opérations ou méthodes) des objets (instances) associés
à cette classe;
• La classe décrit le domaine de définition d'objets. Chaque objet appartient à une classe.
Les généralités sont contenues dans la classe alors que les particularités dans les objets.
Les objets informatiques sont construits à partir de la classe par un processus appelé
instanciation. De ce fait tout objet est une instance de classe.

k.afdel cours Java 38

19
1437-02-19

• Une classe est définie par les attributs et les opérations (méthodes).

– Attributs : Appelés également champs correspondent aux propriétés de la classe. Ils sont définis
par un nom, un type de données et éventuellement une valeur initiale. Un attribut est une variable
qui stocke des données.
Exemple : considérons la classe Employé caractérisée par les attributs code, nom et nbEmployés (nombre
d'employés)

• Les attributs code et nom sont des caractéristiques de chaque objet Employé
contrairement au champ nbEmployés qui est une caractéristique commune à tous les
objets. On dira que nbEmployés est attribut statique.
statique

• Chaque objet, instance d'une classe, donne des valeurs particulières à tous les
attributs définis dans sa classe sauf les attributs statiques ce qui détermine son état.

• Exemples :

k.afdel cours Java 39

Définition :
• Un attribut statique d'une classe est un attribut qui appartient à la classe et qui est
partagé par tous les objets de cette classe. Un attribut statique est considéré comme
étant une variable globale à tous les objets.
• Les attributs statiques ne sont pas instanciés dans les objets“

• Méthodes :
• Les méthodes permettent de décrire les comportements des objets.
• Représentent des procédures ou des fonctions qui permettent d'exécuter un certain
nombre d'instructions.
• Parmi les méthodes d'une classe existe une méthode particulière, qui porte le même
nom que la classe, qui s'appelle le constructeur. Le rôle du constructeur étant créer les
objets de la classe en les initialisant.

k.afdel cours Java 40

20
1437-02-19

Exemple d'implémentation la classe Employé avec java:


class Employe {
/ / Les attributs
int code;
String nom ;
static int nbEmployes
nbEmployes==0 ;
/ / Constructeur
Employe ( ) {
++nbEmployes;
code=nbEmployes ;
)
/ / Les méthodes
void afficheCode () { System. out. println ( "Le code est : " + code ) ;
void afficheNom () { System.out. println ("Le nom est : " + nom) ;}
}

k.afdel cours Java 41

Création d'un objet à partir d'une classe


• L'opération de création d'un objet à partir d'une classe s'appelle
instanciation.
• Pour créer un objet en Java, il faut utiliser le mot clé new, suivi du nom du
constructeur de la classe, avec les parenthèses et les arguments éventuels.
• Par exemple, pour créer une instance de la classe Employé (ou, en d'autres
termes un objet de type Employé), nous utiliserons la syntaxe suivante:
new Employe () ;
• L'objet ainsi créé n'est identifié par un nom. C'est un objet qui ne peut pas
être exploité une fois qu'il est créé. C'est donc un objet perdu en mémoire.
mémoire
Comment retenir les objets :les Handles
Nous pouvons utiliser immédiatement l'objet ainsi créé en utilisant par exemple
La syntaxe suivante : (new Employe
Employe()() ). afficheCode
afficheCode()
() ;
• Cette instruction permet de créer un objet de la classe Employe et en même
moment appelle la méthode afficheCode() pour afficher le code de cet
employé.
• Si nous voulons pouvoir l'utiliser plus tard, il faut, avant de confier cet objet
à Java, s'assurer que nous pourrons le récupérer. Pour cela, il suffit de
pouvoir l'identifier.
k.afdel cours Java 42

21
1437-02-19

Création des handles


• Création d’un handle d'objet. Il suffit pour cela de le déclarer en indiquant vers quelle
classe d'objets il est susceptible de pointer.
Par exemple, pour créer le handle alpha pouvant pointer vers une instance d'Employe,
nous écrirons :
Exemple
Employe alpha;

Vers quoi pointe ce handle ? Pour l'instant, il ne pointe donc vers rien.
Modifier l'affectation d'un handle
Employe alpha;
new Employe() ;

• Il n'y a ensuite aucun moyen d'établir un lien entre le handle créé à la première ligne et
l'objet créé à la seconde. Il faut donc effectuer l'affectation en même temps que la
création, de la façon suivante :
• Employe alpha;
• alpha = new Employe () ;
Java nous permet même de condenser ces deux lignes en une seule sous la thème :

• Employe alpha = new Employe ( ) ;


k.afdel cours Java 43

Utilisation des membres de l'objet créé


Pour accéder aux membres d'un objet Créé, on utilise son Handle suivi d'un point, puis
du nom de l'attribut ou de la méthode.
Exemple :
alpha . nom= " jamil " ;
aIpha. afficheNom () ;
System. out.println (aIpha.code) ;
System. out.println (alpha.nbEmployes) ;
System. out.println (Employe . nbEmployes) ;
NOTE
Les membres statiques sont accessibles en utilisant soit le handle d'un objet quelconque
k.afdel
de la classe, soit directement le nom decours Java
la classe. 44

22
1437-02-19

La destruction des objets le garbage collector

• Avec certains langages, [e programmeur doit s'occuper lui-même de libérer


la mémoire en supprimant les objets devenus inutiles. C'est une des
principales sources de mauvais fonctionnement des programmes.

• Avec Java, le problème est résolu de façon très simple : un programme,


appelé garbage collector
collector, ce qui signifie littéralement "ramasseur d'ordures",
est exécuté automatiquement dès que la mémoire disponible devient
inferieure à un certain seuil. De cette façon, vous pouvez n'être assuré
qu'aucun objet inutilisé n'encombrera la mémoire au point d'être une cause
de problèmes.

k.afdel cours Java 45

Exemple

1- Ecrire le code java de la classe Emptoye


2- Enregistrer le fichier sous le nom Employe.java
3- Compiler le fichier Employe.java

class Employe { // Les méthodes


// Les attributs void afficheCode(){
System.out.println("Le code est : "
int code ;
+ code) ;}
String nom ; void afficheNom(){
static int nbEmployes =0 ; System.out.println("Le nom est : "
//Constructeur + nom) ; }
Employe() { }
++nbEmployes :
Code=nbEmployes ;
}

k.afdel cours Java 46

23
1437-02-19

Classe TestEmploye :

1- Ecrire le code java de la classe TestEmploye


2- Enregistrer le fichier sous le nom TestEmployejava
3- Compiler ce fichier ( javac TestEmploye.java)
4- Exécuter ce programme fiava TestEmploye)

class TestEmploye{
public static void main(String[] args){
new Employe(); // Crée un objet anonyme
Employe e2 ; //Crée un handle,pour le moment, in pointe vers null
e2=new Employe
Employe();(); //Crée un objet Employe puis affecte son adresse au handle e2
Employe e3=new Employe(); //Crée le handle e3, crée un objet et affecter l'objet au handle e3
e2.nom:"Jamil"; // définit la valeur I'attribut nom de I'objet e2
e2.afficheCode(); // on fait appel à la méthode afficheCode() de I'objet e2
e2.afficheNom();// on fait appel à la méthode afficheNom() de I'objet e2
e3.afficheCode();// on fait appel à la méthode afficheCode() de I'objet e3
System.out.println("Nombre d'employés en utilisant I'objet e2--" + e2.nbEmployes);
System.out.println( "Nombre d'employés en utilisant I'objet e3 :"+ e3.nbEmployes ) ;
System.out.println("Nombre d'employés en utilisant la classe Employe" +
e2.nbEmployes);
}}
k.afdel cours Java 47

k.afdel cours Java 48

24
1437-02-19

Héritage
Le développement d'une application Java peut se décomposer en deux
phases:
• La 1ière phase de conception, consiste à représenter l'univers du problème
à l'aide d'un ensemble de classes ( digramme des classes UML).
• La 2ième implémentation, consiste à construire ces classes.

La phase de conception est la plus importante car elle conditionne le bon


déroulement de la phase d'implémentation.Si la conception est mauvaise,
aussi bonne que soit la qualité de l'implémentation, l'application sera peu
efficace, voire ne fonctionnera pas.

La première chose à faire pour développer une application consiste donc à


faire la liste des classes qui seront nécessaires, ce qui consiste à découper
l'univers du problème en catégories d'objets (les classes.

Cependant, avant de pouvoir concevoir un modèle efficace, il est nécessaire de


comprendre le système hiérarchique qui régit les relations entre les classes
Java.
k.afdel cours Java 49

Dans Java, tous les éléments que manipule un programme sont des objets objets, à
l'exception des primitives. Cependant, les primitives peuvent être traitées
comme des objets grâce aux enveloppeurs.
Si l'on considère la hiérarchie suivante :

k.afdel cours Java 50

25
1437-02-19

L’héritage
• Les classes Chien, Chat et Canari sont des sous classes de la
classe Animal ; on dira que la classe Chien hérite de la classe
Animal.
• De même, les classes Teckel, Labrador et Caniche, héritent de la
classe Chien et donc par transitivité, héritent également toutes las
caractéristiques de la classe Animal.

• Dans java la super classe d’une hiérarchie de classes est une classe
prédéfinie nommée Object.
Autrement dit, si une classe n’hérite pas d’une autre, elle hérite
automatiquement de la classe Object.

• On peut également dire que toutes la classes héritent de la classe


Object par hiérarchie.

k.afdel cours Java 51

• la classe Animal
Animal class Animal {
// Attributs : // Attributs
vivant : boolean boolean vivant; int âge;
age : int // Constructeur
Animal (int a) { âge = a; vivant = true;}
//Constructeur : //Méthodes
Animal(int a) void vieillit() {++âge;}
//Méthodes : void meurt() {vivant = false;}
crie() void crie() {}
vieillit() }
Meurt()

Ce qui signifie qu'un animal possède un état (vivant, qui peut être vrai ou faux et âge,
qui est une valeur numérique) et sait faire plusieurs choses ( crie(), vieillit() et meurt(),
qui sont des méthodes).
• La méthode vieillit() permet d’incrémenter d’une unité l’attribut âge.
• La méthode meurt() initialise l’attribut vivant à false.
• La méthode crie() ne fait rien, mais sa présence indique qu'un Animal crie(), mais
pour le moment, on ne connaît pas la nature de son crie.
La création d'un Animal se ferait à l'aide de l'instruction suivante :
Animal nouvel Animal = new Animal (3 (3);

k.afdel cours Java 52

26
1437-02-19

La classe Canari dérive de la classe Animal :


class Canari extends Animal {
}
Référence à la classe parente
• La classe Canari hérite de la classe Animal tous ses membres sauf le constructeur. Notre
nouvelle classe a besoin d'un constructeur. Ce constructeur prendra pour paramètre un entier
indiquant l'âge du canari. On peut écrire la classe Canari de la manière suivante :

class Canari extends Animal class Animal {


{ // Attributs
boolean vivant; int âge;
// Constructeur de la classe Canari
// Constructeur
Canari(int a){ Animal (int a) { âge = a; vivant = true;}
âge=a ; vivants true ;} //Méthodes
} void vieillit() {++âge;}
void meurt() {vivant = false;}
class Canari extends Animal { void crie() {}
Canari(int a){ }
Super(a) ;
}
}

• Pour éviter de réécrire, dans le constructeur de la classe Canari, les mêmes instructions du
constructeur de la classe Animal, on peut faire appel au constructeur de la classe parente en
utilisant l'identificateur super
super.

k.afdel cours Java 53

Remarque : La seule chose, dans notre modèle, qui distingue un Canari d'un autre
Animal est son cri.
Pour mettre en œuvre cette différence, nous devons utiliser une technique appelée
method overriding, en anglais, que l'on peut traduire par redéfinition de méthode.
La redéfinition des méthodes
• La classe Canari hérite de la classe Animal la méthode crie().
• Or cette méthode ne convient pas à la classe Canari car on connaît
maintenant la nature du crie d’un canari.
• Avec les concepts de l’héritage, nous avons la possibilité de redéfinir cette
méthode pour en créer une nouvelle version.
La classe Canari s’écrit à nouveau de la manière suivante :

class Canari extends Animal {


Canari(int a){
Super(a) ;
}
void crie() { System.out.println("Cui-
System.out.println("Cui-cui !"); }
}

k.afdel cours Java 54

27
1437-02-19

Le test de la classe

class Animaux {
public static void main(String[] args) {
Canari titi = new Canari(3);
titi.vieillit();
titi.crie(); }
}

• Appel au constructeur de la classe Animal pour la création de l’objet Canari « titi » en


utilisant l’identificateur super(a)
super(a), avec a=3, ce qui permet d’initialiser l’attribut âge à 3
(âge=3) et vivant à true.

• Appel à la méthode vieillit() de l’objet titi. Cette méthode n’a pas été définie dans la
classe Canari, mais elle a été hérité de la classe Animal.
Animal Cet appel permet
d’incrémenter l’attribut âge de l’objet titi (âge=4).

• La dernière instruction fait appel à la méthode crie() de l’objet titi. Comme la


méthode crie() a été redéfinie dans la classe Canari, c’est cette version qui sera
exécuté. Ce qui permet d’afficher le message « cui-cui ! »

k.afdel cours Java 55

Surcharger les méthodes


• Nous voulons ne souhaiter l'anniversaire des animaux qu'une fois de temps en temps, mais pas tous les
ans.
• Nous pourrions modifier la méthode vieillit() afin qu'elle prenne un paramètre indiquant le nombre
d'années à ajouter à l'âge.
• Cependant, nous voulons conserver la possibilité d'utiliser la méthode sans paramètre si le vieillissement
est de 1.
Pour cela, il nous suffit de créer dans la classe Animal une deuxième version de la méthode avec le même nom :

class Animal { boolean vivant; int âge ; Animal al=new Animal(4) ;


Animal (int a) { âge = a ; vivant = true; al .vieillit() ; // pour incrémenter âge d’une année
System.out.println("Un animal de "+a+"an(s)vient d'être créé"); al.vieillit(3) ; // incrémenter âge de 3 ans
}
void vieillit() {++âge;
System.out.println("C'est l'anniversaire de cet animal."); On parle de la surcharger de la méthode vieillit()
System.out.println("Il a maintenant " + âge + " an(s).");
} • Surcharger une méthode consiste simplement à
void vieillit(int a) { la définir plusieurs fois avec le même nom.
âge += a;
System.out.println("C'est l'anniversaire de cet animal.");
Question
System.out.println("Il a maintenant " + âge + " an(s).");
} Comment fait l'interpréteur pour savoir quelle
void meurt() { version il doit exécuter?
vivant = false; Rép : Il utilise tout simplement pour cela la
System.out.println("Cet animal est mort"); signature de la méthode.
} Question :
void crie() { }
Qu’est ce qu’est la signature d’une méthode ?
}

• On peut constater que la méthode vieillit() est un cas particulier de la méthode vieillit(int a) avec a=l. la méthode vieillit()
peut donc s’écrire d’une manière plus optimisée de la manière
k.afdel courssuivante
Java : 56
void vieillit() { vieillit(1); }

28
1437-02-19

Cours Online Java


http://www.learningadapt.com/

k.afdel cours Java 57

k.afdel cours Java 58

29
1437-02-19

Signature d'une méthode


• La signature d'une méthode désigne la liste de ses paramètres avec leur type.
• les deux méthodes vieillit ont des signatures différentes. L'une prend un paramètre de
type int, l'autre ne prend aucun paramètre.
• Si la méthode vieillit() est appelée avec un paramètre de type int ou sans paramètre, le
compilateur sait quelle version il doit choisir.
• En revanche, un appel avec un paramètre d'un autre type, ou plusieurs paramètres,
produit une erreur.
Remarque
Pour identifier les signatures des méthodes, Java utilise également l'ordre des paramètres.
Exemple : les deux méthodes suivantes :
g(int a, long b)
g(long b, int a)
ont des signatures différentes.
En revanche, le nom des paramètres ne distingue pas les signatures.
Remarque
Une même classe ne pourra donc contenir les deux méthodes suivantes :
f(int a, long b)
f(int c, long d)
Ces deux méthodes ont la même signature, ce qui produirait une erreur de compilation.

k.afdel cours Java 59

Surcharger les constructeurs


Les constructeurs peuvent également être surchargés.
Notre classe Animal possède un constructeur qui prend pour paramètre une valeur de type
int.
Cependant, si la plupart des instances sont créées avec la même valeur initiale, nous
pouvons souhaiter utiliser un constructeur sans paramètre.
Supposons, par exemple, que la plupart des instances soient créées avec 1 pour valeur
initiale de âge.
Nous pouvons alors réécrire la classe Animal de la façon suivante :
class Animal { boolean vivant; int âge ;
// Premier constructeur
Animal () {âge = 1; vivant = true;
System.out .println ("Un animal de ,,+a+"an(s)vient d'être créé");}

// Deuxième constructeur
Animal (int a) { âge = a; vivant = true; Animal al = new Animal();
System.out .println ("Un animal de ,,+a+,,an (s) vient d'être créé");} // âge=l Ou en indiquant l’age :
void vieillit(){++âge; Animal a2 = new Animal(4);
System.out.println("C1 est l'anniversaire de cet animal."); // âge=4
System.out.println("Il a maintenant " + âge + " an(s) ;}

void vieillit(int a) { âge += a;


System.out.println("C'est l'anniversaire de cet animal.");
System.out.println("Il a maintenant " + âge + " an(s).");}

void meurt(){vivant = false;


System.out.println("Cet animal est mort");}
void crie(){ }
} k.afdel cours Java 60

30
1437-02-19

• De la même manière que les deux méthodes vieillit() et vieillit(int a), le premier
constructeur est un cas particulier du deuxième.

• Pour éviter de réécrire deux fois les mêmes instructions dans les deux constructeur, on
peut faire appel au deuxième constructeur à l’intérieur du premier.

• Toutefois, l’appel d’un constructeur à l’intérieur d’un autre ne peut pas se faire en
écrivant son nom mais en utilisant le mot this suivi des arguments du constructeur
appelé entre parenthèse.
• Le premier constructeur peut s’écrire d’une manière plus optimisée comme suit:
// Premiser Constructeur
Animal () {
this(l) ; // au lieu de Animal(1)
}
// Deuxième Constructeur
Animal (int a) {
âge = a; vivant = true;
System.out .println ("Un animal de" +a+" an (s) vient d'être créé");
}
Les constructeurs par défaut
• En l’absence du constructeur dans une classe, java fournit automatiquement un
constructeur par défaut. Le constructeur par défaut est le suivant :
k.afdel cours Java 61
NomDeLaClasse ( ) { }

class Animal { class TestAnimaux {


boolean vivant; public static void main(String[]
int âge; args)
int ageMaxi = 10 ; {
Animal (int a) { âge = a; vivant = true;
Canari titi = new Canari(3);
System.out.println("Un animal de " + a+ " an(s) vient
d'être créé");} Canari mimi=new Canari() ;
Animal( ) { this (1) ; } titi.ageMaxi=5 ;
titi.vieillit();
void vieillit(int a) { âge += a;
titi.crie();
if (âge > ageMaxi)
titi.vieillit(4);
meurt () ;
Else{ System.out.println("C1 est 11 anniversaire de cet mimi.vieillit(5);
animal.") ; mimi.crie() ;
System.out.println("Il a maintenant " + âge + " an(s)");} } }
void vieillit() { vieillit(1) ; } }
void meurt (){ vivant = false;
System, out .println ("Cet animal est mort") ; }
void crie ( ) {}
}
// La classe Canari
class Canari extends Animal {
Canari(int a) { super(a); }
Canari(){ super () ; }
k.afdel cours Java 62
void crie ( ){ System. out.println (f,Cui-cui ! ”) ;}
}

31
1437-02-19

Encapsulation
• Encapsulation en Java est un concept qui renforce la protection des variables,
des méthodes de l'extérieur de la classe;
• Encapsulation est un concept pour mieux gérer ce fragment de code pour qui
il est moins d'impact ou aucun impact sur d'autres parties du programme;
• L'importance de l'encapsulation se manifeste dans un environnement qui est
sujette à changement fréquents comme c’est la cas dans le domaine de
développement qui confronté à des exigences de logiciels changent tous les
jours.
• L'idée derrière le concept de l'encapsulation est que si une fonctionnalité qui
est bien encapsulé dans le code c-à-d maintenu dans un seul endroit et non
dispersés dans tous le code- est facile à changer et à gérer.
• Langage Java fournit de nombreux mode pour encapsuler les membres d'une
classe.
– Mode private pour encapsuler complètement un membre que ce soit un attribut ou
une méthode en Java
– Mode protected ou public pour obtenir un degré moindre d'encapsulation

k.afdel cours Java 63

Exemple
• Supposons que nous ayons une classe PRET avec un constructeur et que
dans les différentes classes vous avez créés des instances de la class
PRET en utilisant le constructeur.
• Les exigences logicielles ont maintenant changés et vous devez inclure
l'âge de l'emprunteur.
• Puisque ce code n'est pas bien encapsulé-à-dire ne se limite pas à un seul
endroit-vous devez changer partout où vous appelez ce constructeur.

k.afdel cours Java 64

32
1437-02-19

public class PRET {


class A{
private int periode ; //private variables examples of encapsulation
// attribut
private String prêt_type;
private String preteur;
private String salaire; public A(…){…}
void m1(int p, String ptype, String prteur, String sal)
public PRET(int periode, String prêt_type, String preteur, String salaire) { PRÊT prt= new PRÊT(p,ptype, prteur,sal);}
{ super(); }
this.periode = periode;
this.prêt_type = prêt_type; class B{
this.preteur = preteur;
// attribut
this.salaire = salaire;}
public A(…){…}
double f2(int p, String ptype, String prteur, String sal)
public PRET(int periode, String prêt_type, String preteur, String salaire
, int age) {
{ PRÊT prt= new PRÊT(p,ptype, prteur,sal);}
super(); }
this.periode = periode;
this.prêt_type = prêt_type; class C{
this.preteur = preteur; // attribut
this.salaire = salaire; public A(…){…}
This.age = age;} double g(int p, String ptype, String prteur, String sal)
{ PRÊT prt= new PRÊT(p,ptype, prteur,sal);}
public int getPeriode() {return periode;} }
public void setPeriode(int periode) {this.periode = periode;}
public String getPrêt_type() {return prêt_type;}
public void setPrêt_type(String prêt_type) { this.prêt_type = prêt_type;}
public String getPreteur() {return preteur;}
public void setPreteur(String preteur) { this.preteur = preteur;}
public String getSalaire() {return salaire;}
public void setSalaire(String salaire) { this.salaire = salaire;}
}
k.afdel cours Java 65

Solution
• Dans notre exemple nous allons encapsuler la logique de création de l'objet de la
classe PRET dans la méthode CreatePRET () autrement dit la création de l'objet va
s'effectuer dans une seul endroit en appelant le constructeur à l'intérieur de la
méthode CreatPret().
• Le client peut appeler cette méthode qui va créer l'objet PRET. Maintenant s'il ya
modification comme le cas d'ajouter l'âge du Prêteur dans ca cas il suffit de modifier
uniquement le constructeur dans la méthode CreatePRET() et non pas aller chercher
la où se trouve le constructeur pour le modifier.
class PRET //no argument consustructor omitted here
{
private int periode ; //private variables
// create PRET can encapsulate PRET -
examples of encapsulation
Object creation logic
private String prêt_type;
public PRET CreatePRET(){
private String preteur;
private String salaire;
//processing based on loan type and
then returning loan object
//public constructor can break
/*PRÊT pret_obj= new PRÊT(p,ptype,
encapsulation instead use factory method
prteur,sal);*/
private PRET(int periode, String pret_typ
e, String preteur, String salaire){
PRÊT pret_obj= new PRÊT(p,ptype,
this. periode = periode;
prteur,sal, ag);
this. pret_type = pret_type;
this. preteur = preteur;
return pret_obj;
this. salaire = salaire;
} }
}
k.afdel cours Java 66

33
1437-02-19

Advantage de l’Encapsulation
1. code encapsulé est plus souple et plus facile à changer avec les nouvelles
exigences logicielle.
2. Encapsulation en Java facilite le test unitaire
3. Encapsulation en Java vous permet de contrôler qui peut accéder à quoi.
4. Encapsulation contribue également à écrire classe immuable en Java qui
sont un bon choix dans un environnement multi-threading.
5. Encapsulation réduire le couplage de modules et de renforcer la cohésion
à l'intérieur d'un module parce que tout morceau de code est encapsulé
dans un seul endroit.
6. Encapsulation vous permet de modifier une partie du code sans affecter
autre partie du code.

k.afdel cours Java 67

Niveaux d'encapsulation
Les 4 niveaux d'encapsulation de Java sont par ordre de visibilité croissante :
• un membre privé (private) n'est visible que dans les instances
• directes de la classe où il est déclaré.
• un membre sans modifieur est visible uniquement dans les instances
directes de la classe où il est déclaré et dans celles des classes du
même paquetage.
• un membre protégé (protected) n'est visible que dans les instances,
directes ou non, de la classe où il est déclaré (et donc aussi dans les
instances des sous-classes) et dans les instances des classes du
même paquetage.
• un membre public (public) est visible par n'importe quel objet.

k.afdel cours Java 68

34
1437-02-19

•Les variables membres déclarées private sont bien encapsulés vous ne pouvez
modifier ou accéder à ces variable directement qu'à l'intérieur de cette classe.
• si vous souhaitez autoriser les classes extérieur à accéder à ces variables il faut
créer les méthodes d’accès (accesseur) getter et setter

k.afdel cours Java 69

k.afdel cours Java 70

35
1437-02-19

Visibilité des membres selon leurs modifieurs et le niveau


d'encapsulation

Modifieur classe paquetage Sous-classe Autres-classe

private visible

visible visible

protected visible visible visible visible

public visible visible visible visible

package ma.ac.fsa.tp package ma.ac.fsa.tp2

k.afdel cours Java 71

Encapsulation des classes


Une classe (ou interface) déclarée public est visible de partout, sinon elle n'est visible
que dans son paquetage

package monPaquetage; package monPaquetage;


public abstract class Liste{ class ImplémentationDeListe extends Liste{
public void ajoutElement(Object o); ...
public Object enleverElement(Object o); }
public boolean estVide();
public Liste creerListe(){
return new ImplementationDeListe();
}
...
}

Remarque
Les classes qui ne sont pas déclarées dans un paquetage font toutes partie du même
paquetage « anonyme ».

k.afdel cours Java 72

36
1437-02-19

Une classe peut servir à plusieurs choses :


• Créer des objets, en étant instanciée.
• Créer de nouvelles classes, en étant étendue.
• On peut utiliser directement ses membres statiques (sans qu'elle soit instanciée.)
• On peut utiliser les membres de ses instances.
Java dispose de mots clés permettant de modifier la façon dont les éléments peuvent
être utilisés.'
1- static :
• Un élément déclaré static appartient à une classe et non à ses instances.
• Dans l'exemple de la classe Voiture la primitive capacité aurait été déclarée static.
Les objets instanciés à partir d'une classe ne possèdent pas les éléments de cette
classe qui ont été déclarés static.
• Un seul élément existe pour la classe et il est partagé par toutes les instances.
• Les variables static
• Si la classe Voiture-contient la primitive statique capacité et la primitive non statique
carburant, et si nous instancions cette classe pour créer l'objet maVoiture la
syntaxe utilisé est :
maVoiture.carburant =30 ;
• Normalement, capacité appartient à la classe Voiture, et il est possible d'y accéder
en utilisant la syntaxe : Voiture.capacité=80 ;
Remarque -
Cependant, Java nous permet également k.afdeld'utiliser
cours Javala syntaxe : maVoiture.capacité=80 73
;

Les méthodes static


Les méthodes peuvent également être statiques.
Dans ce cas, elles appartiennent à la classe et ne sont pas instanciées dans les
objets de cette classe.
Les méthodes statiques, sont accessibles directement en utilisant le nom de la
classe ou indirectement en utilisant le nom de l’instance de la classe.
Exemple de la classe Voiture
• La méthode getCapacité() peut être déclarée static car . elle ne fait référence
qu'à des membres static (en l'occurrence la variable capacité).
public static int getCapacite(){
return capacité; // une méthode qui manipule les membres static est
static }

Remarques :
Comme dans le cas des variables, les méthodes static peuvent être référencées
à l'aide du nom de la classe ou du nom de l'instance.
Il est important de noter que les méthodes static ne peuvent en aucun cas faire
référence aux méthodes ou aux variables non static de la classe.
Elles ne peuvent non plus faire référence à une instance. (La référence this ne
peut pas être employée dans une méthode static.)
• Les méthodes static ne peuventk.afdel
pas non
coursplus
Java être redéfinies dans les classes
74
dérivées.

37
1437-02-19

2- final
• Java ne dispose pas de constantes. Ce n'est pas une limitation, car Java
dispose d'un mécanisme beaucoup plus puissant qui permet non seulement
d'utiliser une forme de constantes, mais également d'appliquer ce concept à
d'autres éléments comme les méthodes ou les classes.
Les variables final
• Une variable déclarée final ne peut plus voir sa valeur modifiée. Elle remplit
alors le rôle d'une constante dans d'autres langages.
• Une variable final est le plus souvent utilisée pour encoder des valeurs
constantes.
Par exemple: final float pi = 3.14;
Les variables final non initialisées
• Il existe en fait deux types de constantes dans un programme : celles dont
la valeur est connue avant l'exécution du programme, et celles dont la
valeur n'est connue qu'au moment de l'exécution.
• Une variable final non initialisée est simplement déclarée de la façon
suivante : final int a;
Evidemment, cette variable ne pourra pas être utilisée avant d'être initialisée.
Une fois initialisée au moment de l’exécution, sa valeur ne peut plus être
modifiée.
k.afdel cours Java 75

Les méthodes final


• Les méthodes peuvent également être déclarées final,
• les méthodes final ne peuvent pas être redéfinies dans les classes dérivées.
• Vous devez donc utiliser ce mot clé lorsque vous voulez être sûr qu'une
méthode d'instance aura bien le fonctionnement déterminé dans la classe
parente.
• Pour déclarer une méthode final, il suffit de placer ce mot clé dans sa
déclaration, de la façon suivante :
final int calcul (int i, in j) {
//code
}
Remarque
S'il s'agit d'une méthode static, il n'est pas nécessaire de la déclarer final car
les méthodes static ne peuvent jamais être redéfinies.
Les classes final
• Une classe peut également être déclarée final, dans un but de sécurité ou
d'optimisation.
• Une classe final ne peut pas être étendue pour créer des sous-classes.
• Par conséquent, ses méthodes ne peuvent pas être redéfinies et leur accès
peut donc se faire directement, sans recherche dynamique.
k.afdel cours Java 76

38
1437-02-19

3- abstract
Le mot clé abstract peut être employé pour qualifier une classe ou une méthode.
Une méthode déclarée abstract ne peut pas être exécutée. En fait, elle n'a pas d'existence réelle. Sa
déclaration indique simplement que les classes dérivées doivent la redéfinir.
Dans l'exemple de la classe Animal, la méthode crie() aurait pu être déclarée abstract :
abstract class Animal { abstract void crieO;
}
• Nous savons simplement qu'un animal a un cri mais on ne peut pas définir le cri de l’animal.
• C'est exactement la signification du mot clé abstract. La méthode ainsi définie indique qu'une
sous-classe devra définir la méthode de façon concrète.

Les méthodes abstract présentent les particularités suivantes :


• Une classe qui contient une méthode abstract doit être déclarée abstract elle-même.
• Une classe abstract ne peut pas être instanciée.
• Une classe peut être déclarée abstract, même si elle ne comporte pas de méthodes abstract.
• Pour pouvoir être instanciée, une sous-classe d'une classe abstract doit redéfinir toutes les
méthodes'abstract de la classe parente.
• Si une des méthodes n'est pas redéfinie de façon concrète, la sous-classe est elle-même
abstract et doit être déclarée explicitement comme telle.
• Les méthodes abstract n'ont pas de définition. Leur déclaration doit être suivie d'un point-
virgule.

k.afdel cours Java 77

Les interfaces
• Une classe peut contenir des méthodes abstract et des méthodes non abstract.
• Il existe une catégorie particulière de classes qui ne contient que des méthodes
abstract : interfaces.
• Les interfaces sont toujours abstract, sans qu'il soit nécessaire de l'indiquer
explicitement.
• De la même façon, il n'est pas nécessaire de déclarer leurs méthodes abstract.
• Les interfaces obéissent par ailleurs à certaines règles supplémentaires.
– Elles ne peuvent contenir que des variables static et final (des constantes).
– Elles peuvent être étendues comme les autres classes, avec une différence
majeure : une interface peut dériver de plusieurs autres interfaces.
– En revanche, une classe dérive toujours d'une autre classe et peut dériver, en
plus, d'une ou de plusieurs interfaces. Une classe est définie de la manière
suivante :
interface nomlnterface extends interfl, interf2, interface3,.... { //déclaration des constantes de l'interface
elles sont //implicitement de type static final MAX=3 ;
MIN=1 ;
// déclaration des méthodes abstraites. Elles sont implicitement //de type public abstract void afficher()
; int getNom() ;}
• Une classe peut hériter d’une seule classe et de plusieurs interfaces. La
syntaxe est la suivantes :
class maClasse extends autreClasse implements
interfl, interf 2, interf 3,... { }
k.afdel cours Java 78

39
1437-02-19

4- transient :
• Le mot clé transient s'applique aux variables d'instances (primitives et objets). Il
indique que la variable correspondante est transitoire et que sa valeur ne doit pas
être conservée lors des opérations de sérialisation.
• La sérialisation sera étudiée dans un prochain chapitre. Sachez simplement pour
l'instant que cette opération permet d'enregistrer sur disque un objet Java afin de le
conserver pour une session ultérieure, ou de l'envoyer à travers un réseau.
• Lors de la sérialisation, tous les champs de l'objet sont sauvegardés à l'exception de
ceux déclarés transient.
5- synchronized
• Le mot clé synchronized modifie également les conditions d'accès aux classes et
aux objets. Il concerne uniquement les programmes utilisant plusieurs threads, c'est-
à-dire plusieurs processus se déroulant simultanément.
• Java permet de réaliser facilement ce genre de programme. Par exemple, vous
pouvez concevoir un programme dans lequel des objets d'un tableau sont modifiés
fréquemment.
• De temps en temps, le tableau doit être trié pour améliorer les conditions d'accès.
• Cependant, les objets ne doivent pas être modifiés pendant que le tri s'exécute. Il
faut donc s'assurer que la méthode permettant de modifier un élément du tableau ne
pourra pas accéder à celui-ci lorsque le tri est actif.

k.afdel cours Java 79

Polymorphisme

k.afdel cours Java 80

40
1437-02-19

• Polymorphisme exprime le besoin de structurer son


environnement en fonction du problème qu'il a à
résoudre.
Exemple
• Pour un enfant de 8 ans, un vélo est un objet du même
type qu'un ours en peluche ou un ballon de football.
Exprimé en Java, nous dirions que Vélo une instance de
la classe Jouet.
• Pour un adulte, un vélo pourra être un objet du même
type qu'une voiture ou une moto, c'est-à- dire une
instance de la classe Véhicule.
• Pour un industriel fabriquant également des brouettes,
des échelles ou des étagères métalliques, un vélo sera
simplement une instance de la classe Produit.

k.afdel cours Java 81

Nous avons certainement tous appris à l'école qu'il était impossible


d'additionner des pommes et des oranges. Cette affirmation accepte
l'idée qu'un problème ne peut être traité qu'à travers une structure
unique rigide.
Pourtant, un enfant de cinq ans est à même de comprendre que :
3 pommes + 5 oranges = 8 fruits
• Un autre problème peut surgir lorsqu'un objet paraît pouvoir
appartenir à une structure ou une autre suivant l'angle sous lequel
on aborde le problème.
Par exemple,
il paraît naturel de définir une classe Cheval comme dérivant de la
classe Animaux. Cependant, il peut exister également une classe
MoyenDeTransport, qui serait éventuellement également
candidate.
Un objet peut-il être à la fois un animal et un moyen de transport ?
Le bon sens nous indique que oui, tout comme nous savons qu'un
objet peut être à la fois une pomme et un fruit.
Attention : la relation n'est pas la même dans les deux cas.
k.afdel cours Java 82

41
1437-02-19

Transtypage & Polymorphisme


Le sur-casting des objets
• Une façon de décrire l'exemple consistant à additionner des pommes et des oranges
serait d'imaginer que nous disons pommes et oranges mais que nous manipulons en
fait des fruits.
Exemple
• 3 fruits (qui se trouvent être des pommes)
• + 5 fruits (qui se trouvent être des oranges)
• = 8 fruits
• Cette façon de voir les choses implique que les pommes et les oranges soient
"transformés" en fruits préalablement à l'établissement du problème.
• Cette transformation est appelée sur-casting, bien que
Le terme Sur- interpelle la classe de base des deux classe pomme et orange

Avec la syntaxe de Java, nous écririons quelque chose comme :


• 3 (fruits)pommes + 5 (fruits)oranges
• = 8 fruits

k.afdel cours Java 83

Instanciation et héritage
Pour qu'un objet puisse être considéré comme une instance de la classe Pomme ou une
instance de la classe Fruit, Il faut donc que, lors de l'initialisation, un objet de chaque
classe soit créé.
Exemple:
abstract class Fruit{ class Pomme extends Fruit{
int poids; Pomme(int p){ this.poids=p;
Fruit ( ) { System.out.println("création d'une pomme de "+
System.out.println("Création d'un fruit"); poids+" grammes ");}
} void affiche(){
void affiche(){ System.out.println("C'est une pomme");}
System.out.println("c’ est un fruit"); void affichePoids(){
}} System.out.println("le poids de la pomme est
:"+poids + " grammes");}}
//**********************************************************
class Orange extends Fruit{
Orange(int p){ poids=p; //************************************************
System.out.println("création d'une orange de "+ class Polymorphisme{
poids+" grammes"); } public static void main(String[] args){
void affiche(){ Pomme p=new Pomme(72);
System.out.println("C'est une Orange");} Orange o=new Orange(80);
void affichePoids(){ }
System.out.println("le poids de l'orange est:"+poids+ }
"grammes");}}
//*******************************************************

k.afdel cours Java 84

42
1437-02-19

Remarque
La classe Fruit est abstract car on ne souhaite pas qu'il soit possible de créer un fruit
sans indiquer de quel type de fruit il s'agit.

• La classe Polymorphisme, qui est la classe principale du programme, contient une


méthode main. Dans cette méthode, nous créons une instance de Pomme, puis une
instance d'Orange.
Nous obtenons le résultat suivant :
Création d'un fruit
création d'une pomme de 72 grammes
Création d'un fruit
création d'une orange de 80 grammes
Que se passe-t-il ?
• Nous nous apercevons qu'avant de créer une Pomme, le programme crée un Fruit,
comme le montre l'exécution du constructeur de cette classe.
• La même chose se passe lorsque nous créons une Orange.

k.afdel cours Java 85

Le sur-casting des objets


Considérons l’exemple Test suivant qui utilise les mêmes classes Fruits, Pomme et
Oranges Précédentes.

class Polymorphisme2
{ public static void main(String[] args){
Fruit f1; //Création d'un handle fl de type Fruit
Fruit f2; //Création d'un handle f2 de type Fruit
f1=new Pomme(60); //sur-casting implicit
f2=(Fruit)new Orange (40); // surcasting explicit } }

• Un objet de type Pomme peut être affecté à un handle de type fruit sans aucun
problème :
• f1=new Pomme(60);
• Dans ce cas l’objet Pomme est converti automatiquement en Fruit. On dit que l’objet
Pomme est sur- casté en Fruit.
• Dans java, le sur-casting peut se faire implicitement.
• La casting explicit se fait en précisant la classe vers laquelle on convertit l’objet entre
parenthèse. Exemple : f2=(Fruit)new Orange(40);

k.afdel cours Java 86

43
1437-02-19

Le sous-casting des objets


class Polymorphisme3{ public static void main(String[] args){
Fruit fl;
Fruit f2;
fl=new Pomme(60);
f2=new Orange(40);
fl.affichePoids(); // Le sous casting ne se fait pas implicitement}}

• En compilant ce programme, l’erreur suivante est affichée :


• Polymorphisme3.java: 5 : cannot résolve symbol symbol : method affichePoids () location: class
Fruit
• f 1. affichePoids ();// Erreur de compilation, le sous casting ne se fait pas implicitement : 1 error
Ce message indique que l’objet fl qui est de type Fruit ne possède pas la méthode affichePoids().
Cette méthode est définie dans les classes Pomme et Oranges et non dans la classe Fruit.
En fait, même si le handle f1 pointe un objet Pomme, le compilateur ne tient pas en considération
cette affectation, et pour lui f1 est un Fruit.
• Nécessité d’une conversion explicitement l’objet f1 qui de type Fruit en Pomme: Sous-casting
• Dans ce cas de figure, le sous-casting doit se faire explicitement. L’erreur de compilation peut être
évité en écrivant la syntaxe suivante :
• ((Pomme)f1).affichePoids();
Cette instruction indique que l’objet f1 , de type Fruit, est converti en Pomme, ensuite la
méthode affichePoids() de l’objet Pomme est appelé ce qui est correcte.

k.afdel cours Java 87

Le « late binding »
Early binding, (liaison précoce) : Le lien entre l'appel et la méthode est alors établi au
moment de la compilation Java utilise cette technique pour les appels de méthodes
déclarées final. Elle a l'avantage de permettre certaines optimisations. En revanche,
pour les méthodes qui ne sont pas final, Java utilise la technique du late binding
(liaison tardive). Le lien entre l'appel et la méthode est alors établi au moment de l’
exécution
Exemple :
La méthode affiche() possède 3 versions définies dans les classes Fruit, Pomme et
Orange.
Grâce au late binding, java est capable de déterminer, au moment de l’exécution, quelle
version de méthode qui sera appelée ce que nous pouvons vérifier par le programme
suivant :
class Polymorphisme4{ L’exécution de ce programme donne :
public static void main(String[] args) Création d'un fruit
{ Fruit f1; creation d'une pomme de 60 grammes
Fruit f2;
f1=new Pomme(60); Creation d'un fruit
f2=new Orange (40); creation d'une orange de 40 grammes
f1.affiche();
f2.affiche();} } C'est une pomme
C'est une Orange

k.afdel cours Java 88

44
1437-02-19

• La classe Fruit possède elle aussi la méthode affiche(), le compilateur


n’affiche pas d’erreur lorsqu’on écrit fl.affiche(), mais au moment de la
compilation, java ne fait pas de liaison avec quelle version de méthode à
appeler.
• Au moment de l’exécution, on constate que l’instruction f1.affiche(),
provoque l’exécution de la méthode affiche() de la classe Pomme, ce qui
conrespond à la réalité car le handle fl pointe une instance de la classe
Pomme.
• Ici, grâce au polymorphisme, le sous- casting se fait implicitement, ce qui
signifie qu’avant l’appelle de la méthode affiche(), l’objet Fruit f1 est
transformé automatiquement en Pomme
class Polymorphisme4{ L’exécution de ce programme donne :
public static void main(String[] args) Création d'un fruit
{ Fruit f1; creation d'une pomme de 60 grammes
Fruit f2;
f1=new Pomme(60); Creation d'un fruit
f2=new Orange (40); creation d'une orange de 40 grammes
f1.affiche();
f2.affiche();} } C'est une pomme
C'est une Orange

k.afdel cours Java 89

Tableaux Objet
Déclaration : LesFruits
• Exemple : Tableau d’objets Fruit
• Fruit[] lesFruits;
Création du tableau.
• lesFruits = new Fruit[5];
Création des objets:
• lesFruits[0]=new Pomme(60);
• lesFruits[l]=new Orange(lOO);
• lesFruits[2]=new Pomme(55);
Manipulation des objets:
• for(int i=0;i<lesFruits.length;i++) lesFruits[i].affiche();
Remarque :
• Un tableau d’objets est un tableau de handles

class Polymorphisme5{
public static void main(String[] args ) {
// Tableau de fruits
Fruit[] lesFruits;
lesFruits=new Fruit[3];
lesFruits[0]=new Pomme(60);
lesFruits[1]=new Orange(70);
lesFruits[2]=new Pomme(55);
for(int i=0;i<lesFruits.length;i++) lesFruits[i].affiche();}}
k.afdel cours Java 90

45
1437-02-19

Vecteur
La classe Verctor du package java.util est une structure qui représente un tableau dynamique
d’objets de type Object.
Déclaration :
• Vector lesFruits;
Création du vecteur
• lesFruits= new Vector();
Affectation des objets au vecteur
• lesFruits.addElement(newPomme(60));
• lesFruits.addElement(newOrange(100));
• lesFruits.addElement(newPomme(55));
Manipulation des objets:
• for(int i=0;i<lesFruits.size();i++) ((Fruit)lesFruits.elementAt(i)).affiche();
Autes méthodes de la classe Vector: removeElement(int index)
Exemple
import java.util.*; // pour la classe Vector class
Polymorphisme6{
public static void main(String[] args){
// Vecteur de fruits
Vector lesFruits=new Vector();

lesFruits.addElement(new Orange (80))


lesFruits.addElement(new Pomme (70))
lesFruits.addElement(new Pomme(66))

for(int i=0;i<lesFruits.size();i++)
//lesFruits.elementAt(i).affiche() // Sous-Casting Obligatoire
k.afdel cours Java
((Fruit)lesFruits.elementAt(i)).affiche();} 91

Les entrées/sorties
• Pour effectuer une entrée ou une sortie de
données en Java il faut
– Ouverture d’un moyen de communication;
– Écriture ou lecture des données;
– Fermeture du moyen de communication
– En java, les moyens de communication sont
représentés par des objets particulier les flux
ou stream

k.afdel cours Java 92

46
1437-02-19

Les entrées/sorties avec Java


• Pour effectuer une entrée ou une sortie de
données en Java il faut
– Ouverture d’un moyen de communication;
– Écriture ou lecture des données;
– Fermeture du moyen de communication
– En java, les moyens de communication sont
représentés par des objets particulier les flux
ou stream

k.afdel cours Java 93

• Les stream relient le programme et un élément


particulier appelé Sink (evier ou zone tampon);
• Les objets qui communiquent avec les entrées-
sorties sont les stream de communication
• Les objet qui traitent les informations en
provenances des stream de communication sont
des streams de traitement
• Certaines stream permettent d’enregistrer sur
disque des objets Java cette opération est
appelé Sérialisation

k.afdel cours Java 94

47
1437-02-19

Serialisation
class Carrosserie implements Serializable {
String valeur;
Carrosserie (String s){
valeur =s;
}
String getValeur()
{return valeur; }
}
class Moteur implements Serializable {
String valeur;
Moteur (String s)
{ valeur=s; }
String getValeur()
{return valeur; }
k.afdel cours Java 95
}

public class serialisation{


public static void main (String [] args) throws
IOException{
voiture voiture1= new voiture ("V6", "Cabriolet");
voiture voiture2=new voiture("v5"," peugeot");
voiture1.setCarburant(50);
voiture2.setCarburant(100);
FileOutputStream f= new FileOutputStream("garage");
ObjectOutputStream o=new ObjectOutputStream(f);
o.writeObject(voiture1);
o.writeObject(voiture2);
o.close();
}
}

k.afdel cours Java 96

48
1437-02-19

Deserialisation
import java.io.*;
public class deserialisation {
public static void main (String [] args) throws IOException,
ClassNotFoundException {
FileInputStream f= new FileInputStream ("garage");
ObjectInputStream o=new ObjectInputStream(f);
voiture voiture1
voiture1=(voiture)o.readObject();
voiture voiture2
voiture2=(voiture)o.readObject();
o.close();
System.out.println("Carrosserie : "+ voiture1.getCarrosserie());
System.out.println("Moteur : "+ voiture1.getMoteur());
System.out.println("Carburant : "+ voiture1.getCarburant());
System.out.println("Carrosserie : "+ voiture2.getCarrosserie());
System.out.println("Moteur : "+ voiture2.getMoteur());
System.out.println("Carburant : "+ voiture2.getCarburant());}}

k.afdel cours Java 97

Accès Directe
La classe RandomAccessFile
• Les entrées /sortie vue jusqu’à présent
sont de type séquentiel
• Inconvénient avec ce type d’accès
– Il faut beaucoup de temps pour accéder à des
données depuis le début;
• Les fichier à accès direct n’utilise pas des
stream il utilise la classe
RandomAccessFile qui dérive de la classe
Object
k.afdel cours Java 98

49
1437-02-19

import java.io.*;
public class AcessDirect{
public static void main (String[] args) throws IOException{
RandomAccessFile original, copie;
File f1=new File("originale.jpg");
File f2=new File("copîe.jpg");

original = new RandomAccessFile(f1, "r");


copie=new RandomAccessFile(f2,"rw");
int c;
while ((c=original.read())!=-1)
copie.write(c);
original.close();
copie.close();
}
}

k.afdel cours Java 99

Interprétation des modèles UML avec JAVA

• Nous allons montrer les grandes lignes de passage entre un modèle UML
et Java dans ses cas les plus courants.

CAS D'ASSOCIATION 1 - 1

public class A public class B


{private B b=new B(…);} { private A leA;}

CAS D'ASSOCIATION 1 – n

public class A public class B


{ private B[ ] tabB = new B[ n ] ; } { private A leA; }
k.afdel cours Java 100

50
1437-02-19

NAVIGABILITÉ RESTREINTE

public class A public class B


{ private B[ ] tabB = new B[ n ] ;} { // pas de référence à un objet de la classe A
}

k.afdel cours Java 101

Implémentation en Java

public class A {
public abstract class A {
public A() {
...
...
}
}
….
}
public interface A {
...
Exemple }
public class A {
public String a1; public class A {
package String a2; ...
protected String a3; }
private String a4;
public void op1() { public class B extends A {
... ...
} }
public void op2() { public interface Ia {
... ...
} }
}
public class A implements Ia {
...
}

k.afdel cours Java 102

51
1437-02-19

Association bidirectionnelle 1 vers 1

public class A { public class B {


private B rb; private A ra;
public void addB( B b ) { public void addA( A a ) {
if( b != null ){ if( a != null ) {
if ( b.getA() != null ) { // si b est déjà if (a.getB() != null) { // si a est déjà
connecté à un autre A connecté à un autre B
b.getA().setB(null); // cet autre A doit se a.getB().setA( null ); // cet autre B
déconnecter doit se déconnecter
} }
this.setB( b ); this.setA( a );
b.setA( this ); a.setB( this );
} }
} }
public B getB() { return( rb ); } public void setA(A a){ this.ra=a; }
public void setB( B b ) { this.rb=b; } public A getA(){ return(ra); }
} }
k.afdel cours Java 103

Association unidirectionnelle 1 vers 1

public class A {
private B rb; public class B {
public void addB( B b ) { ... // La classe B ne connaît pas l'existence de la classe A
if( b != null ) { this.rb=b; } }
}
} Association bidirectionnelle

public class A {
private ArrayList <B> rb;
public A() { rb = new public class B {
ArrayList<B>(); } private A ra;
public ArrayList <B> getArray() public B() {}
{return(rb);} public A getA() { return (ra); }
public void remove(B public void setA(A a){ this.ra=a; }
b){rb.remove(b);} public void addA(A a){
public void addB(B b){ if( a != null ) {
if( !rb.contains(b) ){ if( !a.getArray().contains(this)) {
if (b.getA()!=null) if (ra != null) ra.remove(this);
b.getA().remove(b); this.setA(a);
b.setA(this); k.afdel cours Javara.getArray().add(this); } } 104
rb.add(b); } }} }
}

52

Vous aimerez peut-être aussi