Vous êtes sur la page 1sur 74

Programmation Orientée Objet

avancée

Dr. Sofiane HACHICHA


Institut Supérieur d’Informatique et de Multimédia de Gabès
sofiane.hachicha@isimg.tn

MPSSI1 2023/2024
Partie 1

Programmation Orientée Objet avec Java

2
Qu'est-ce que Java ?

Un langage de programmation orienté objets


Un ensemble d'API variées
Un ensemble d'outils (le JDK)
 un compilateur de sources java : javac
 un interpréteur de Bytecode (JVM) : java
 un documenteur : javadoc
 un désassembleur de classe : javap
 un débogueur : jdb
 une archive : jar
 des bibliothèques de classe standard
 …

3
Bref historique
 1990 : Développé chez SUN Microsystems par
James Gosling, Mike Sheridan et Patrick Naughton
 nommé Oak puis appelé Java (café en argot américain).
 1995 : Lancé HotJava browser développé en Java
 Janv. 96 : JDK 1.0
 Fév. 97 : JDK 1.1

 2009 : SUN a été rachetée par la société Oracle

 Sep. 2021 : JDK 17 (version LTS)
 Sep. 2023 : JDK 21

4
Un exemple de code
class Bonjour {
public static void main (String args[]) {
System.out.println("Bonjour ISIMG!");
}
}

 La compilation : le programme javac


Bonjour.java Bonjour.class

class Bonjour ... >javac Bonjour.java


0010110110001110

(code source) (Bytecode)


 Exécution : on interprète le fichier Bytecode
 >java Bonjour
 Depuis Java 11, il est possible d’exécuter
directement un mono-fichier, sans compilation :
 >java Bonjour.java

5
Notions dans le monde objets
 Objets & Classe Programmation Objet = Polymorphisme

 propriétés & méthodes redéfinition


 Encapsulation
 constructeurs & destructeurs Héritage méthodes

 surcharge & redéfinition


 Héritage Objets
 Polymorphisme

Si vous savez déjà à quoi


correspondent ces termes, vous
pouvez quitter le cours ;-) !

6
Programmation structurée vs.
Programmation objet
Programmation structurée Programmation objet

 C, Pascal, ...  Java, C++, ...


 Programme :  Question:
procédures – fonctions Sur quoi porte mon
 Question: programme ?
Que doit faire mon
programme ?
 structure !
  les entités manipulées

 traitements

7
Principe des modèles objets
 Les modèles à objets ont été créé pour
modéliser le monde réel
 Toute entité du monde réel est un objet
 Tout objet représente une entité du monde
réel
 un exemple : Article
Article

Référence Désignation Quantité Prix Unitaire

8
Objet
objet
=
données + opérations sur ces données (méthodes)
=
variable de "type abstrait" (non scalaire)
=
entité du domaine du problème
Exemple d'objets : des voitures
objet R21_de_mon_chef objet ma_Clio
genre : Renault genre : Renault
plaque : 2245 TUN 115 plaque : 4357 TUN 93
NbPlaces : 5 NbPlaces : 4
propriétaire: chef propriétaire: Moi
s_arreter() s_arreter()
avancer() avancer()
fin objet fin objet

9
Programme objet
 Un programme = une société d'entités
 Son exécution : les entités s'entraident pour résoudre le
problème final en s'envoyant des messages.
 une entité = un objet qui prend en compte sa propre
gestion (objet responsable)
 un message = est traduit en appel de méthode

10
Principe d’encapsulation
Encapsulation
=
regroupement de code et de données
masquage d'information au monde extérieur
 Un objet est composé de 2 parties :
 partie publique : opérations qu'on peut faire dessus
 partie privée : partie interne (intime) = données sensibles
de l'objet (les attributs et les autres méthodes)
 Les utilisateurs de l'objet ne voient (c.-à-d. ne peuvent
utiliser et ceci est contrôlé par le compilateur) que la
partie publique
 Objectifs :
 Seul l’objet peut modifier ses propre attributs
 Masquer les détails de l’implémentation

11
Principe d’encapsulation
 Objectif :
comportement état
Interface = partie
publique

message Méthodes Attributs

 Catégories d’autorisation d’accès :


 public : aucune restriction
 private & protected : accès réservé (private est plus
restrictive que protected)

12
Classe
classe
=
modèle décrivant le contenu et le comportement des futurs objets
de la classe
=
ensemble d'objets

le contenu = les données


le comportement = les méthodes
Exemple: la classe des véhicules, la classe des camions, des voitures.
La classe des voitures peut être décrite par :
classe Voiture
genre
plaque
NbPlaces
propriétaire
s_arreter()
avancer()
fin classe

13
Résumé :classe & objet
 classe & objet, méthode et message :
 Un exemplaire particulier d'une classe s'appelle une
instance de la classe ou un objet de cette classe :
objet = instance de classe
 Une classe est un agrégat d'attributs et de méthodes : les
membres
 En première approche:
 les objets sont à la programmation objet ce que sont les
variables à la programmation structurée
 Les classes sont à la programmation objet ce que les
types sont à la programmation structurée
programmation procédurale Variable type

Programmation objet Objet classe

 Envoyer un message à un objet c'est lui demander


d'exécuter une de ses méthodes.

14
Déclaration d’une classe
 Format classique d’un fichier java: import: on le voit
plus loin dans le
import classes; cours

class NomClasse
{ main() est optionnel: il permet
Attribut(s) de la classe; d’executer la classe via la JVM:
>java NomClasse
Méthode(s) de la classe;

public static void main(String args[])


{
}
}
 Une classe est un ensemble d'attributs et de méthodes : les
membres
 le corps des méthodes sont définies directement à l’intérieur de
la classe

15
Classes et objets : exemple
Propriété / méthode
class Cercle { référence d’un objet :Cercle c;
double x, y; créer un objet: l'opérateur new
double r; constructeur

Cercle(double R) {
r = R;
}
double aire() {
return 3.14159 * r * r;
}
}

class MonPremierProgramme
{
public static void main(String[] args) {
Cercle c; // c est une référence sur un objet Cercle, pas un objet
c = new Cercle(5.0); // c référence maintenant un objet alloué en mémoire

c.x = c.y = 10;


System.out.println("Aire de c :" + c.aire());
}
}

16
Syntaxe : classes & objets
CLASSE OBJET
 tout est défini à l'intérieur de  En Java il faut construire
classe : il n'y a rien de global explicitement les objets ( new )
 Les méthodes sont définies directement  Par la suite les objets construits
dans la classe
seront repérés et accessibles
 les constantes aussi grâce à leur référence initialisée
 On définit les classes par : au moment de la construction de
class nomClasse { l'objet.
type_donnees données
définition des méthodes  On a donc :
Voiture ma_Clio;
}
déclaration d'une référence.
 par exemple :
class Voiture {  Puis
String genre; ma_Clio = new Voiture();
String immatriculation;
int NbPlaces;  Ayant une référence ma_Clio
String propriétaire; initialisée, on l'utilise alors pour
void s_arreter(){ ... } lancer toute méthode sur l'objet
void avancer(float nbmetres) (i.e. pour envoyer tout message à
{ ... } l'objet) par :
} ma_Clio.avancer(4.5);

17
Constructeur
 Pour initialiser un objet, on utilise une méthode "spéciale" appelée
constructeur (même nom que la classe sans valeur de retour)
 elle est appelé automatiquement au moment du new
class Cercle {
double x, y, r;
Cercle(double X, double Y, double R) {
x = X; y = Y; r = R;
}
Cercle(Cercle c) {
x = c.x; y=c.y; r=c.r;
}
Cercle() {
x=y=r=0;
}
}
 Toute classe possède un constructeur par défaut, implicite.
 Celui-ci peut être redéfini (ici le dernier constructeur)
 Une classe peut avoir plusieurs constructeurs qui diffèrent par le
nombre et/ou la nature de leurs paramètres (surcharge)

18
La surcharge
 Dans une classe, plusieurs méthodes ou constructeurs
peuvent coexister avec un même nom si elles ont des
signatures différentes.
 La signature est constituée de :
 nombre de ces paramètres
 type de chacun de ces paramètres.
 Exemple :
class Cercle {
double x, y, r;
void Initialiser(double X, double Y, double R) {
x = X; y = Y; r = R;
}
void Initialiser(Cercle c) {
x = c.x; y=c.y; r=c.r;
}
void Initialiser() {
Initialiser(0.0, 0.0, 0.0);
NOTE: “Initialiser” peut etre
} remplacé par le constructeur
}

19
Destruction d'un objet
 La destruction des objets est prise en charge par
le garbage collector (GC).
 Le GC détruit les objets pour lesquels il n'existe
plus de référence.
 Les destructions sont asynchrones (le GC est
géré dans un thread de basse priorité).
 Aucune garantie n'est apportée quant à la
destruction d'un objet.
 Si l'objet possède la méthode finalize(),
dépréciée depuis Java 9, celle-ci est appelée
lorsque l'objet est détruit.

20
Héritage (1)
Héritage
=
construire une classe à partir d'une autre
=
Notion rattachée aux classes
héritage simple: héritage = dérivation
 La classe dont on dérive est dite classe
de base (ou parente ou mère)
 Les classes obtenues par dérivation
sont dites classes dérivées.
 L'héritage permet de reprendre
intégralement tout ce qui a déjà été
fait et de pouvoir l'enrichir
(réutilisabilité)
 en dérivant, on établit ainsi une
spécialisation

Automobile et Camion héritent (ou


dérivent) de Vehicule.
21
Héritage (2)
 Une sémantique forte :  syntaxe :
 Lorsqu'une classe B hérite  Java utilise le mot clé
d'une classe A, les objets de B réservé extends :
seront considérés aussi class SuperClasse // ou classe mère
comme une "sorte" d'objet A. {
// Attributs et méthodes
}
 L'héritage entre classes
traduit la sémantique "est class SousClasse extends SuperClasse
// ou classe fille
une sorte de" :
{
- une automobile "est une // Attributs supplémentaires
sorte de " véhicule // Méthodes propre à la classe
- donc la classe automobile }
hérite de la classe Vehicule
 par exemple:
class Camion extends Vehicule {
double tonnage;
String typeChargement()

{ … }
}

22
Héritage (3)
 Une classe ne peut hériter (extends) que d'une
seule classe à la fois.

 Les classes dérivent toujours, par défaut, de


java.lang.Object

 Une référence d'une classe C peut contenir des


instances de C ou des classes dérivées de C.

 L'opérateur instanceof permet de savoir à quelle


classe appartient une instance.

23
Héritage (4)
class Ellipse {
double r1, r2;
Ellipse(double r1, double r2) { this.r1 = r1; this.r2 = r2;}
double aire(){return 0;}
}
class Cercle extends Ellipse {
Cercle(double r) {super(r, r);}
double getRayon() {return r1;}
}
class MonSecondProgramme
{
public static void main(String[] args) {

Ellipse e = new Ellipse(2.0, 4.0);


Cercle c = new Cercle(2.0);
System.out.println((e instanceof Cercle));
System.out.println((e instanceof Ellipse));
System.out.println((c instanceof Cercle));
System.out.println((c instanceof Ellipse));
e = c;
System.out.println((e instanceof Cercle));
System.out.println((e instanceof Ellipse));
double r = e.getRayon();
c = e;
c = (Cercle)e;
double r = ((Cercle)e).getRayon();
}
}

24
Le masquage des variables
 Une classe peut définir des variables portant le
même nom que celles de ses classes ancêtres

 Une classe peut accéder aux attributs redéfinis de


sa classe mère en utilisant super ou par cast.

 Le mot clef super fait référence à la classe


parente

25
Spécialisation des méthodes
 On considère 2 classes liées par l'héritage.
Par exemple :
class Employee { . . . }
class Manager extends Employee { . . . }
 Souvent une méthode est définie dans la classe de base, mais a besoin
d'être "affinée" dans la classe dérivée. On a par exemple :
class Employee {
long calculPrime() { return 1000; } // une prime pour un employé
}

class Manager extends Employee {


long calculPrime()
{ return 5000; } // une prime plus importante pour un manager
}
 Les 2 méthodes calculPrime() de ces 2 classes ont même signature. On
dit que la méthode calculPrime() de la classe Manager spécialise la
méthode calculPrime() de la classe Employee.

 Autre terminologie: Spécialisation = Redéfinition

26
Polymorphisme (1)
 Le nom de la méthode calculPrime() désigne 2 codes distincts. Autrement
dit l'identificateur calculPrime représente "plusieurs formes" de code
distinct. On parle de polymorphisme.
 On utilise le polymorphisme à l'aide d'une référence d'objet de classe de
base. Par exemple on écrit en Java :
Employee e = new Employee();
e.calculPrime(); // lance la méthode calculPrime() de la classe Employee

 mais on peut écrire aussi:


e = new Manager();
e.calculPrime(); // lance la méthode calculPrime() de la classe Manager

 Un des avantages de ceci est de pouvoir utiliser une seule référence e de la


classe Employee pour référencer un Employee ou un Manager. C'est possible
car un Manager (classe dérivée de la classe Employee) est une sorte de
Employee : sémantique de l'héritage.
 Autre exemple : si une automobile "est une" sorte de véhicule, alors la classe
automobile hérite de la classe véhicule, et une référence de type véhicule
peut contenir des instances de véhicule ET de automobile
Règle
Une référence d'objet de classe de base (mère) peut aussi contenir des instances des classes filles

27
Polymorphisme (2)
 Le gros avantage du polymorphisme est de pouvoir référencer des
objets sans connaître véritablement leur classe (mais celle d’une
classe mère), et de pouvoir par la suite, lancer le code approprié à
cet objet au moment de l'exécution du programme (et non pas à la
compilation).
 On peut ainsi écrire un code comme par exemple
int calculSalaire(Employe e)
{
int salaire = e.calculSalaireDeBase();
salaire += e.calculPrime();
return salaire;
}

 Au moment de la compilation, le compilateur ne sait pas si c'est la


méthode calculPrime() de la classe Employee ou celle de la classe
Manager qui sera lancée.
 Autrement dit, la liaison entre l'identificateur calculPrime() et le
code à lancer est déterminée à l'exécution du programme :
la liaison est dynamique

28
Polymorphisme (3)
Reprenons l’exemple précédent :
(1)Employee e = new Employee();
(2)e.calculPrime(); // lance la méthode calculPrime() de la classe Employee
(3)e = new Manager();
(4)e.calculPrime(); // lance la méthode calculPrime() de la classe Manager
 Si e référence un Manager (ligne 3), le code (ligne 4) de la méthode e.calculPrime() de
la classe Employee ne sera pas exécuté
Le code à lancer est déterminé suivant la classe de l'objet et non
pas la classe de la référence à cet objet
Comment cela fonctionne ?
 Un appel : e.calculPrime() recherche au moment de l'exécution l'objet référencé par e
 A partir de cet objet, l'interpréteur cherche si la méthode calculPrime() existe dans la
classe de cet objet. Si c'est le cas, cette méthode est lancée et le processus est terminé.
 Sinon, l'interpréteur refait cette recherche dans la classe de base, et ainsi de suite
 Une exception est levée si une telle méthode n'est pas trouvée dans les classes parentes
 En conclusion, il est fondamental de voir que pour utiliser le polymorphisme, il faut :
 avoir au départ une arborescence d'héritage sur les classes en jeu
 utiliser des références d'objet de la classe de base (la classe mère)
 avoir (au moins) deux méthodes de même signature définies l'une dans la classe de
base, l'autre dans la classe dérivée.

29
Surcharge vs. Polymorphisme
 Il ne faut pas confondre les notions de surcharge et polymorphisme
(ou liaison dynamique) qui ont finalement peu de point commun.
 Voici un tableau qui résume les différences :

Surcharge Polymorphisme

Héritage nul besoin nécessite une


arborescence de classes
signature des doivent différer doivent être les mêmes
méthodes
résolu à la compilation l'exécution

30
Partie 2

Mots clefs spéciaux

31
Mot-clé static (1)
 Placé devant un attribut ou une méthode
 static int count = 0;
 static Cercle bigger(Cercle c1, Cercle c2) {…}

 Effet: Il n'est pas nécessaire d'instancier la classe pour


accéder à ses membres statiques (de l’extérieur d’une
classe on peut faire directement
Nom_classe.nom_statique)
 Les attributs static sont communs à toutes les
instances de la classe
 Les méthodes static sont l’equivalent des fonctions
en C

 Les membres statiques (appelés aussi members de


classe) sont accessibles via la classe (au lieu d’une
instance de la classe pour les members d’instance)

32
Mot-clé static (2)
class Cercle {
static int count = 0;
int x, y, r;
Cercle(int R) {r = R; count++;}
boolean plusGrand(Cercle c) {
if (c.r > r) return false; else return true;
}
static Cercle bigger(Cercle c1, Cercle c2) {
if (c1.r > c2.r) return c1; else return c2;
}
}
public class Principale {
public static void main (String args[]) {
int n = Cercle.count;
Cercle c1 = new Cercle(10);
Cercle c2 = new Cercle(20);
n = Cercle.count;
n=Cercle.x;
n=c1.x;
boolean sup = c1.plusGrand(c2);
boolean gran = Cercle.plusGrand(c2);
Cercle c4 = Cercle.bigger(c1, c2);
n=c4.count;
Cercle.count =10;
}
}

33
Constantes: static final
 Une constante est une variable static final
 Exemple: static final float pi = 3.14f ;
 « final » signifie que la valeur n ’est plus
modifiable
 (on peut utiliser final sans static !)
 Dans l’exemple précédent, ça donnerait:
class Cercle {
static int count = 0;
static final double PI = 3.14;
double x, y, r; final pour éviter par exemple
Cercle.PI = 3.14 dans le main.
...

34
Mot clef final
 final : Mot clef qui s’applique à une classe, méthode ou
propriété.
 Classe : final indique que la classe ne peut plus être
héritée
 Méthode : final indique que la méthode ne peut pas
être redéfinie dans les classes dérivées.
 Une méthode static ou private est
automatiquement final
 Propriété : final indique qu’il s’agit d’une constante.
Une propriété final ne peut être affectée qu’une
seule fois.

35
Mot clef this
 Le mot clef this fait référence à l’instance en cours
quand on est dans le code de la classe.
 il permet de différencier les attributs d’une classe
des paramètres passées à une méthode
 Exemple:
class Cercle {
double r;
Cercle(double r) {
this.r = r;
}
...
 Il peut être aussi utilisé pour invoquer un constructeur
de la même classe
 Exemple : Cet ligne fait appel au
public Cercle () { constructeur ci-dessus
this ( 1.0 ) ;
}
 Note: les méthodes statiques ne peuvent pas accéder à this

36
Mot clef super (1)
 Vous savez que grâce à l’héritage:
 Une classe peut définir des attributs portant le
même nom que ceux de ses classes ancêtres
(masquage)
 Une classe peut définir des méthodes portant le
même nom que celles dans sa classe mère
(redéfinition)
 Le mot clef super est un préfixe qui fait référence à la
classe parente
 Grace à super, une classe peut accéder aux
attributs et méthodes de sa classe mère

37
Mot clef super (2)
class A {
int x=1;
void m() {...}
}
class B extends A{
int x=2;
void m() {...}
}
class C extends B {
int a, x=3;
void m() {...}
void test() {
a = x;
a = super.x;
a = super.super.x;
a = ((A)this).x;
a = ((B)this).x;
super.m();
super.super.m();
((A)this).m();
}
}

38
Mot clef super (3)
 Le mot clef super permet d’appeler le constructeur
(tous les types de constructeur) de la classe mère
 public class Ellipse {
double r1, r2;
Ellipse(double r1, double r2) { this.r1 = r1; this.r2 = r2;}
}

final class Cercle extends Ellipse {


int color;
Cercle(double r) {super(r, r); color=0; }
}

 le constructeur de Cercle fait appel au constructeur


parent plutôt que d’initialiser lui-même r1 et r2
 il peut ensuite faire tout autre initialisation qui lui est
propre (color=0;)
 Remarque : le mot clef super doit apparaître à la
première ligne du constructeur.

39
Mot clef abstract
 abstract : Mot clef qui s’applique à une classe ou une
méthode
 une méthode est dite abstraite si on ne veut écrire que le
prototype (=la « signature ») - pas le corps
 Si dans une classe, au moins une méthode est déclarée
abstract, alors la classe le devient
 L’implémentation (=le corps) de la méthode s’effectue dans
les classes qui héritent de cette classe
 Pour ne plus être abstraite, une classe fille doit implémenter
toutes les méthodes abstraites de la classe dont elle hérite
 Si une classe est déclarée abstract, alors elle ne peut pas être
instanciée (pas de new possible)
abstract class C1 { class C2 extends C1{
abstract void toto( ); void toto( ){
void normale( ){ // corps de la méthode
// corps de la méthode }
} }
}

40
Mots clefs
 Une méthode peut :
 Appartenir à la classe (static)
 Appartenir aux instances (sans static)
 Ne pas avoir d’implémentation (abstract)
 Bloquer toute redéfinition (final)

 Une classe peut :


 être non instanciable (abstract)
 Bloquer tout héritage (final)

41
Partie 3

Packages, Visibilités

42
Les packages
 Un package regroupe un ensemble de classes sous un
même espace de noms
 L'intérêt est de regrouper les classes par thème, lien
logique, dépendance…
 un package équivaut à un répertoire contenant des
fichiers classes
 un package peut contenir des sous-packages
 pour utiliser des classes contenues dans un package, il
faut soit :
 utiliser leur nom long package.souspackage.classe
 utiliser la clause import (avec ou sans « * »)
 Les API de java sont organisées en packages (ex:
java.lang, java.io, java.net …)

43
Packages personnalisés (1)
 L'instruction package indique à quel package appartient
la ou les classe(s) du fichier.
 package doit être la première instruction du fichier
source
 Par défaut (si pas d'instruction package dans le fichier)
une classe appartient au package anonyme.
 Exemple :
package forme;

class Cercle {
double x, y, r;
void Cercle(double x, double y, double r) {
this.x = x; this.y = y; this.r = r;
}
...

44
Packages personnalisés (2)
 L'arborescence des répertoires contenant les classes doit être
identique à l'arborescence des packages
 les noms des packages/répertoires sont case sensitifs
 par defaut le package anonyme est le repertoire courant
 Une classe Cercle appartenant au package Forme.2D doit se
trouver dans le fichier Forme/2D/Cercle.class
sources packages répertoires

Package Forme;
... Forme

Package Forme.2D;
... 2D

Package Forme.3D; 3D
...

 Le compilateur sait créer automatiquement les sous-


répertoires pour y placer les fichiers classes

45
Encapsulation & Visibilité (1)
Mots clés utilisable pour gérer les droits d’accès pour un
membre (variable ou méthode) :
 public
 visible par toutes les autres méthodes à l’intérieur
de l’objet ou à l’extérieur.
 protected
 visible uniquement dans sa classe ou sous classe (et
dans le package)
 private
 private sera visible uniquement dans sa classe.
 <sans>
 visible uniquement dans le package en cours -
Equivalent à public mais pour le package

46
Encapsulation & Visibilité (2)

class c1 { Package P1 Package P2


public int A;
protected int B;
int C;
class c4 extends c1 {
private int D;
...
}
}

class c2 extends c1 { class c3 { class c5 {


... ... ...
} } }

A B C D
Accessible par c2 o o o -
Accessible par c3 o o o -
Accessible par c4 o o - -
Accessible par c5 o - - -

47
Partie 4

Interface

48
Héritage et interface (1)
 Une interface est introduite par le mot clé « interface »,
et se comporte comme une classe dont les méthodes
sont par défaut publiques et abstraites et dont tous les
attributs sont final.
 Les mots clés final, abstract, public sont facultatifs dans
la définition d’une interface.
 Une interface est un moyen de préciser les services
qu'une classe peut rendre. C’est un modèle
d'implémentation. Elle est inutilisable en elle-même.
 Depuis Java 8, une interface peut aussi contenir des
méthodes par défaut et/ou des méthodes statiques.
 Une méthode par défaut consiste à spécifier une signature
de méthode avec une implémentation par défaut.
 Depuis Java 9, une interface peut aussi contenir des
méthodes privées et/ou des méthodes statiques
privées.
49
Héritage et interface (2)
 Héritage multiple est interdit entre classes.
 Une interface peut hériter (extends) de plusieurs
interfaces.
 Une classe peut implémenter (implements) une ou
plusieurs interfaces tout en héritant (extends) d'une
classe.
 Une interface fonctionnelle est une interface qui ne
contient qu’une seule méthode abstraite. Elle ne peut
avoir qu’une seule fonctionnalité à exposer.
 Une interface fonctionnelle peut contenir des méthodes par
défaut et statiques qui ont une implémentation, en plus de la
méthode unique abstraite.
 Java fournit une annotation @FunctionalInterface, qui est
utilisée pour déclarer une interface fonctionnelle.

50
Héritage et interface (3)
interface MyInterface {
default void defaultMethod(){
System.out.println("Default");
}
static void staticMethod(){
System.out.println("Static");
}
}
public class MyClass implements MyInterface {
public void defaultMethod(){
System.out.println("Replace Default");
}
public static void main(String[] args) {
new MyClass().defaultMethod();
MyInterface.staticMethod();
}
static void staticMethod(){
System.out.println("another static...");
}
}

51
Héritage et interface (4)
 Une expression lambda est une fonction qui peut être
créée sans appartenir à aucune classe. Elle peut être
transmise comme s’il s’agissait d’un objet et exécutée à
la demande.
 L’expression lambda fournit l’implémentation d’une
interface fonctionnelle.
 Une expression Lambda est en quelque sorte la redéfinition de
l’unique méthode abstraite d'une interface fonctionnelle, sans
avoir à faire une classe.
Syntaxe d’une expression lambda :
(liste de paramètres) -> {corps de la fonction}
<liste de paramètres> : indique les paramètres en entrée de l'unique
méthode abstraite de l'interface fonctionnelle. Ils seront saisis entre () et
il n'est pas obligatoire d'indiquer leurs types ;
-> : c'est le marqueur de l'expression Lambda. Il sépare la liste des
paramètres du corps de la fonction ;
<corps de la fonction> : entre {} ou pas, s'il n'y a qu'une seule
instruction.
52
Héritage et interface (5)
@FunctionalInterface
interface Square {
int calculate(int x);
}
class TestSquare {
public static void main(String args[]){
int a = 5;
// expression lambda pour définir la méthode calculate
//affecter l'expression lambda à l'instance de l'interface fonctionnelle
Square s = (int x) -> x * x;
// return et le paramètre passé doivent être de même type que le prototype
int res = s.calculate(a);
System.out.println(res);
}
}

53
Héritage et interface (6)

class A{
public String f (D obj ) { return "A et D"; }
public String f (A obj ) { return "A et A"; }
}
class B extends A{
public String f (B obj ) { return "B et B"; }
public String f (A obj ) { return "B et A"; }
}
class C extends B{ }
class D extends B{ }

54
Héritage et interface (7)
public class Test {
public static void main (String[ ] args) {
A a1 = new A( ) ;
A a2 = new B( ) ; B b = new B( ) ;
C c = new C( ) ; D d = new D( ) ;
System.out.println (a1.f (b));
System.out.println (a1.f (c));
System.out.println (a1.f (d));
System.out.println (b.f (b));
System.out.println (b.f (c));
System.out.println (b.f (d));
System.out.println (a2.f (b));
System.out.println (a2.f (c));
System.out.println (a2.f (d)) ;
}
}

55
Héritage et interface (8)
class A {
public String f(D obj) { return "A et D"; }
public String f(B obj) { return "A et B"; }
public String f(A obj) { return "A et A"; } }
class B extends A {
public String f(C obj) { return "B et C"; }
public String f(A obj) { return "B et A"; } }
interface X{
default String f(A obj) { return "X et A"; } }
interface Y extends X{
default String f(A obj) { return "Y et A"; } }
class C extends B implements X {
public String f(A obj) { return "C et A"; } }
class D extends C implements Y{
public String f(A obj) { return Y.super.f(obj); } }

56
Héritage et interface (9)
public class Test1 {
public static void main ( String[ ] args) {
A a1 = new A();
A a2 = new B(); B b = new B();
C c = new C();
D d = new D(); X c1 = new D();
System.out.println(c1 instanceof C);
System.out.println(c1 instanceof A);
System.out.println(c1 instanceof Y);
System.out.println(a1.f(new B()));
System.out.println(a1.f(a2));
System.out.println(a2.f(a2));
System.out.println(c.f(b));
System.out.println(d.f(c));
System.out.println(d.f(a2));
B b1= (B)a2;
B b2=(B)a1;
}}

57
Partie 5

Exceptions

58
Exceptions (1)
 Le mécanisme des exceptions permet de gérer de façon
élégante les erreurs pouvant survenir à l’exécution. Elles
présentent trois avantages :
 Obliger les programmeurs à gérer les erreurs.
 Séparer le code de traitement des erreurs du reste du code.
 Rattraper les erreurs en cours d’exécution.
 Lorsqu’une séquence d’instructions est susceptible de
provoquer une erreur, on la place dans un bloc try.
Comme ci-dessous :
try
{ /*
blocs d’instructions
*/
}

59
Exceptions (2)
 On place juste après le bloc try un bloc catch qui permet
de traiter l’erreur :
try
{
/*
blocs d’instructions
*/
}
catch ( nomErreur e )
{
/*
Traitement de l’erreur
*/
}

60
Exceptions (3)
 Une exception est une erreur pouvant être rattrapée en
cours d’exécution.
 Cela signifie que si une erreur survient, une exception est
levée, le code du try est interrompu et le code contenu
dans le catch est exécuté. Par exemple, dans le code
suivant, l’indice i est incrémenté jusqu’à ce que cet indice
dépasse la taille du tableau. Dans ce cas, l’exception
ArrayIndexOutOfBoundsException est levée et le code
correspondant à cette exception dans le catch est exécuté.
try {
int i = 0 ;
int[] tab =new int[10];
while ( true )
System.out.println(tab[i++]);
}
catch ( ArrayIndexOutOfBoundsException e ){
System.out.println("Une exception est survenue") ; }
61
Exceptions (4)
 Si vous rédigez une méthode susceptible de lever une
exception, vous devez la déclarer en ajoutant à son
entête l’expression throws <listeExceptions>.
 Par exemple :

public void bourreTableau() throws ArrayIndexOutOfBoundsException


{
int i = 0 ;
int[] tab =new int[10];
while ( true )
System.out.println(tab[i++]);
}
 Vous remarquez qu’il n’y a pas de try ... catch.
Cela signifie que l’erreur doit être rattrapée dans le sous-
programme appelant. Par exemple :

62
Exceptions (5)
try
{
bourreTableau();
}
catch ( ArrayIndexOutOfBoundsException e )
{
System.out.println("Il fallait s’y attendre");
}

 Bref, lorsqu’une instruction est susceptible de lever une


exception, vous devez soit la rattraper tout de suite,
soit indiquer dans l’entête du sous-programme
qu’une exception peut se propager et qu’elle doit
donc être traitée dans le sous-programme appelant.

63
Exceptions (6)
 Propager une exception, c’est laisser le sous-
programme appelant la traiter mais il est possible lorsque
l’on invoque un sous-programme levant cette exception
de la propager encore. Par exemple,

public void appelleBourreTableau() throws ArrayIndexOutOfBoundsException


{
bourreTableau();
}
 On observe que la méthode appelleBourreTableau() se
contente de transmettre l’exception au sous-programme
appelant. Ce mode de fonctionnement fait qu’une exception
non rattrapée va se propager dans la pile d’appels de sous-
programmes jusqu’à ce qu’elle soit rattrapée. Et si elle n’est
jamais rattrapée, c’est la JVM, qui va le faire.

64
Exceptions (7)
 Une exception est tout simplement une classe héritant
de la classe Exception.
class MonException extends Exception
{
public MonException(){
System.out.println("Constructeur");
}
public String toString(){
return "Méthode d’affichage d’un objet !" ;
}
}
 On lève une exception en utilisant la syntaxe :
throw new <nomexception>(<parametres>).
L’instanciation de l’exception se fait donc en même
temps que sa levée. Par exemple :

65
Exceptions (8)
try
{
/*
. . . . . .
*/
throw new MonException() ;
/*
. . . . . .
*/
}
catch ( MonException e )
{
System.out.println(e);
}

66
Exceptions (9)
 Il se peut qu’une même instruction (ou suite
d’instructions) soit susceptible de lever des exceptions
différentes, il est possible dans ce cas de placer
plusieurs catch à la suite du même try.
try
{
bourreTableau(); Notez bien que
} comme toute
catch ( ArrayIndexOutOfBoundException e ) exception hérite de
Exception, le
{
deuxième catch sera
System.out.println("Il fallait s’y attendre");
exécuté quelle que
}
soit l’exception
catch ( Exception e ) levée (sauf si bien
{ entendu le premier
System.out.println(e); catch est exécuté).
}

67
Exceptions (10)
 Il est quelquefois nécessaire qu’une section de code
s’exécute quoi qu’il advienne (par exemple fermer un
fichier). On place dans ce cas une section finally.
try
{
// . . . . . .
}
catch ( /* . . . */ )
{
// . . . . . .
}
finally
{
// . . . . . .
}

68
Exceptions (11)
class Except extends Exception { }
public class TestFinally{
public static void f(int n){ // pas de throws
try
{ if (n!=1)
throw new Except();
}
catch (Except e)
{ System.out.println(" catch dans f - n = " + n );
return ; }
finally
{ System.out.println(" dans finally - n = " + n ); }
}
public static void main (String args[])
{ f(1); f(2); }
}

69
Traitement des exceptions
 Le bloc try est exécuté jusqu'à ce qu'il se termine avec
succès ou bien qu'une exception soit levée.
 Dans ce dernier cas, les clauses catch sont examinées
l'une après l'autre dans le but d'en trouver une qui traite
cette classe d’exceptions (ou une superclasse).
 Les clauses catch doivent donc traiter les exceptions
de la plus spécifique à la plus générale.
 La présence d'une clause catch qui intercepte une classe
d'exceptions avant une clause qui intercepte une sous-
classe d'exceptions déclenche une erreur de compilation.
 Si une clause catch convenant à cette exception a été
trouvée et le bloc est exécuté, l'exécution du
programme reprend son cours.

70
Arbre des exceptions

 Les exceptions en Java sont considérées comme des objets


 Toute exception doit être une instance d'une sous-classe
de la classe java.lang.Throwable

Throwable
Récupérables
le programme a la possibilité
d'attraper ces exceptions

Exception Error
Les exceptions non récupérables
construites par RuntimeException erreurs "systèmes"
l'utilisateur étendent la (plus de mémoire, ...)
ArrayIndexOutOfBoundsException
classe Exception
ArithmeticException Il est recommandé de
Vos Exceptions … ne pas les corriger.
… Exceptions prédéfinies

71
Instruction « try-with-resources »
(1/3)
 Des ressources (comme des fichiers, des flux, des
connexions, etc.) doivent être fermées explicitement par
le développeur pour libérer les ressources sous-jacentes
qu'elles utilisent.
 Utiliser un bloc try / finally pour garantir leur fermeture.
 L'instruction « try-with-resources », apparue dans
Java 7, permet de définir une ressource qui sera
automatiquement fermée à la fin de l'exécution du bloc
de code de l'instruction.
 Tous les objets qui implémentent l'interface
java.lang.AutoCloseable peuvent être utilisés dans une
instruction de type « try-with-resources ».
 InputStream, OutputStream, Reader, Writer (java.io),
Connection, Statement, ResultSet (java.sql) …

72
Instruction « try-with-resources »
(2/3)
 L’interface java.lang.AutoCloseable ne définit qu’une
seule méthode abstraite : la méthode close
 c'est ce qui garantira à l'instruction « try-with-resources »
qu'elle pourra forcer la fermeture de la ressource.
 Si cette instruction est utilisée sur un type n'implémentant pas
cette interface, une erreur de compilation sera produite.
 Avec Java 7, les ressources à libérer sont positionnées
entre parenthèses et directement à la suite du mot
clé try.

// Une seule ressource automatiquement gérée


try ( FileInputStream fis = new FileInputStream( "Fich.txt" ) ) {
// Ici on manipule le fichier
} // Appel à la méthode close automatique

73
Instruction « try-with-resources »
(3/3)
// Deux ressources automatiquement gérées
try ( FileInputStream fis = new FileInputStream( "Fich1.txt" );
FileOutputStream fos = new FileOutputStream( “Fich2.txt" ) ) {
// Ici on manipule les deux fichiers
} // Appel aux méthodes close automatique

 Avec Java 9, il est possible de déclarer une variable


correspondant à une ressource à libérer
automatiquement en dehors du bloc try.
FileInputStream fis = new FileInputStream( “Fich.txt" );
// Une seule ressource automatiquement gérée
try ( fis ) {
// Ici on manipule le fichier
} // Appel à la méthode close automatique

74

Vous aimerez peut-être aussi