Introduction à la programmation Java - BFH

Transcription

Introduction à la programmation Java - BFH
Haute école spécialisée bernoise
Haute école Technique et Informatique, HTI
Section Microtechnique
Introduction à la
programmation Java
Introduction
Aspect procédural de la programmation Java
Introduction à la programmation OO
2004, HTI Burgdorf
Nom de fichier:
Erstellt am:
Autor:
Version:
Introduction_Java_Partie1
5. March 2007
Elham FIrouzi
1.0
E. Firouzi
Introduction à la programmation Java
Tables des matières
Tables des matières
Introdution........................................................................................................................................................1
1.1
Fondement............................................................................................................................................... 1
1.1.1
Propriété du Java ............................................................................................................................. 1
1.1.2
Champ d’application du Java .......................................................................................................... 1
1.1.3
Lecture ............................................................................................................................................ 1
1.1.4
Information disponibles sur le web ................................................................................................. 2
1.2
Un premier exemple ................................................................................................................................ 2
1.3
Développement de programme en Java................................................................................................... 3
1.3.1
Editeur de text ................................................................................................................................. 3
1.3.2
Compilateur..................................................................................................................................... 3
1.3.3
Interpréteur...................................................................................................................................... 3
1.3.4
Vue d’ensemble............................................................................................................................... 4
1.4
Les applications....................................................................................................................................... 4
1.5
Les applets............................................................................................................................................... 4
1.6
Avantages et désavantage du Java........................................................................................................... 7
2
Aspect procédural de la programmation Java ..................................................................................................8
2.1
Introduction ............................................................................................................................................. 8
2.2
Les éléments lexicographiques................................................................................................................ 8
2.2.1
Jeu de caractères.............................................................................................................................. 8
2.2.2
Indicateur ........................................................................................................................................ 8
2.2.3
Les commentaires............................................................................................................................ 8
2.2.4
Les séquences d’échappement......................................................................................................... 9
2.3
Les mots clés ......................................................................................................................................... 10
2.4
Les variables et le type de données élémentaires .................................................................................. 10
2.4.1
Declaration et initialisation de variable......................................................................................... 10
2.4.2
Type de donnée élémentaire.......................................................................................................... 11
2.4.3
Les changements de type de données............................................................................................ 13
2.4.4
La visibilité.................................................................................................................................... 14
2.4.5
Les variables globales ................................................................................................................... 14
2.5
Les chaînes de caractères ...................................................................................................................... 14
2.5.1
String............................................................................................................................................. 14
2.5.2
StringBuffer................................................................................................................................... 15
2.6
Les tableaux .......................................................................................................................................... 16
2.6.1
Les tableaux unidimensionels ....................................................................................................... 16
2.6.2
Les tableaux multidimentionnels................................................................................................... 18
2.7
Les constantes ....................................................................................................................................... 18
2.8
Les opérateurs ....................................................................................................................................... 19
2.8.1
Les opérateurs arithmétiques......................................................................................................... 19
2.8.2
Les opérateurs de comparaison ..................................................................................................... 20
2.8.3
Les opérateurs logiques ................................................................................................................. 20
2.8.4
Les opérateurs de traitement des bits ............................................................................................ 20
2.8.5
Les opérateurs d’affectation .......................................................................................................... 21
2.8.6
L’opérateur point d’intérogation ................................................................................................... 22
2.8.7
L’opérateur cast............................................................................................................................. 22
2.8.8
Les opérateurs supplémentaires pour la programmation OO ........................................................ 22
2.9
Les structures de contrôle...................................................................................................................... 23
2.9.1
Introduction ................................................................................................................................... 23
2.9.2
L’instruction if ............................................................................................................................ 23
2.9.3
L’instruction switch................................................................................................................... 24
2.9.4
La boucle while .......................................................................................................................... 25
1
Version 1.0, 05.03.07
Page II
Introduction à la programmation Java
Tables des matières
2.9.5
La boucle do while................................................................................................................... 26
2.9.6
La boucle for............................................................................................................................... 27
2.9.7
Contrôle des boucles avec les instructions break et continue ............................................... 28
2.10 Les Méthodes ........................................................................................................................................ 29
2.10.1
Nom, Liste de paramètres et valeur de restitution ......................................................................... 29
2.10.2
Signature, prototype et sur chargement (overloading) .................................................................. 31
2.10.3
La récursion................................................................................................................................... 32
2.11 La méthode principale main()............................................................................................................ 32
3
Introduction à la POO avec Java ....................................................................................................................34
3.1
Introduction ........................................................................................................................................... 34
3.1.1
Les problèmes des langage de programmation procédural............................................................ 34
3.1.2
Les types de donnée abstraits ........................................................................................................ 34
3.1.3
Exigences pour les langage de programmation OO ...................................................................... 35
3.2
Caractéristiques des langages OO ......................................................................................................... 35
3.2.1
Abstraction à l’aide d’objet ........................................................................................................... 35
3.2.2
Encapsulage............................................................................. Fehler! Textmarke nicht definiert.
3.2.3
Héritage et polymorphisme ........................................................................................................... 36
3.2.4
Caractéristiques de Java ................................................................................................................ 37
3.3
Les classes et les objets ......................................................................................................................... 37
3.3.1
Définition ...................................................................................................................................... 37
3.3.2
La syntaxe ..................................................................................................................................... 38
3.3.3
Les attributs................................................................................................................................... 38
3.3.4
Les méthodes................................................................................................................................. 38
3.3.5
Modificateur d’accès ..................................................................................................................... 39
3.3.6
Les diagrammes de classe ............................................................................................................. 40
3.3.7
Les méthodes et les attributs de classe .......................................................................................... 41
3.3.8
Instancier un objet, constructeur ................................................................................................... 42
3.3.9
Destructeur et collecteur d’ordure (Garbage Collection) .............................................................. 44
3.3.10
Transmission et retour des objets .................................................................................................. 46
3.3.11
Les classes internes ....................................................................................................................... 47
3.4
Héritage................................................................................................................................................. 48
3.4.1
Fondement..................................................................................................................................... 48
3.4.2
Ordre des constructeurs et des destructeurs................................................................................... 51
3.4.3
Les classes et méthodes abstraites................................................................................................. 53
3.4.4
Polymorphisme ............................................................................................................................. 56
3.4.5
Les casting des classes .................................................................................................................. 57
3.5
Relation entre les classes....................................................................................................................... 58
3.6
Les interface .......................................................................................................................................... 60
3.7
Les paquets............................................................................................................................................ 62
3.7.1
Utilisation et importation .............................................................................................................. 63
3.7.2
Les paquets mis à dispostion par Java........................................................................................... 64
3.7.3
Definition des paquets propres ...................................................................................................... 64
3.7.4
Visibilité........................................................................................................................................ 66
3.8
OO Design............................................................................................................................................. 66
3.8.1
UML.............................................................................................................................................. 66
Version 1.0, 05.03.07
Page III
Introduction à la programmation Java
Introduction
1 Introduction
1.1 Fondement
Java est un langage de programmation moderne, qui a développé par SUN Microsystems. Java a été introduit
officiellement en 1995 et est disponible avec sous licence Open Source depuis 1999.
1.1.1 Propriété du Java
Le langage de programmation Java possède les propriétés suivantes :
•
Orienté objet : Tous les composants, mis à part les types de donnée simple comme les integer, character ou
boolean sont des objets.
•
Indépendant de la plateforme : Les programmes Java peuvent être utilisés presque sur toutes les
plateformes (PC, Mac, Workstation ...) et systèmes d’opération (Windows, MAC-OS, Linux etc.).
•
Interprété : Le code Byte du langage de programmation Java est interprété par la machine virtuelle, en
anglais Virtual Machine (VM). Le code byte peut être interprété soit sous forme d’applet (dans un
explorateur Internet) ou en tant qu’application indépendante.
•
Robuste: Plusieurs dispositifs ont été mis à disposition pour éliminer les erreurs typiques de programmation
(pas de pointer, Garbage Collection ...).
•
Sur : Des modèles de sécurité sont mis à disposition.
•
Dynamique : Java charge uniquement les classes nécessaires à l’application, à travers le réseau.
•
Ouvert : Les modules, qui ont été programmés dans un autre langage, peuvent être intégrés au programme
Java.
•
Applicable en réseau : Une implémentation simple des systèmes en réseau est possible.
•
Graphique: La programmation d’interface graphique (GUI) simple et indépendant de la plateforme est
possible.
•
Multithreading : Java permet d’exécuter des tâches en parallèle et met à disposition des mécanicismes pour
les synchroniser.
•
Bibliothèque de classes : Java met à disposition des multiples bibliothèques.
1.1.2 Champ d’application du Java
Java fut d’abord utilisé dans les secteurs classiques, comme celui des ordinateurs et des applications Internet.
Aujourd’hui Java est de plus en plus utilisé dans les consoles portables (en anglais handheld) comme les
téléphones portables, les agendas électroniques, Set-Top-Boxen etc. Toutefois, Java n’a toujours pas pu
s’affirmer dans le domaine des applications temps réel (voir chapitre 1.6).
1.1.3 Lecture
Programmation en Java, Fritz Jobst, HANSER-Verlag, ISBN 3-446-22061-5
Go To Java 2, Guido Krüger, Addison-Wesley, ISBN 3-8273-1370-8
Version 1.0, 05.03.07
Page 1
Introduction à la programmation Java
Introduction
1.1.4 Information disponibles sur le web
Documentation originale de SUN:
http://java.sun.com/docs
http://java.sun.com/docs/books/tutorial
Différents lien pour Java:
http://www.javabuch.de (HTML-Version des Buches „Go To Java 2“)
http://java.seite.net/ (die deutsche Java-Seite)
http://www.java.de (Java User Group Deutschland)
http://www.javamagazin.com (Web-Seite der Zeitschrift Java-Magazin)
http://www.javaworld.com (Web-Seite der Zeitschrift Java World)
http://javareport.com (Web-Seite der Zeitschrift Java Report)
1.2 Un premier exemple
Un premier exemple pour démontrer la simplicité du code Java :
/**
* First example of java code
*
* @author (FUE1)
* @version (1.0
17.11.03)
*/
public class Ex01
{
/**
* Principal program main()
* @The parameter args[0] contains the number of students
*/
public static void main(String args[])
{
int nbrStudents;
System.out.println("Hello");
// Displays "Hello"
if(args.length > 0)
// Contains the program arguments
{
// yes --> define the number of students
nbrStudents = Integer.parseInt(args[0]);
System.out.println("The class contains " + nbrStudents + " students(s)");
}
System.exit(0);
// end the program
}
}
Le code source Java ne se distingue guère d’un programme C/C++. Les remarques suivantes ont un caractère
introductif. Ils seront traités plus en détail dans les chapitres suivants :
• Un programme Java est composé de plusieurs classes.
• Chaque classe devrait être définie dans un fichier séparé.
• Les commentaire sont définis à l’aide de « /* */ » ou « / / ».
• Les instructions sont définies à l’aide de point-virgule.
• Chaque programme (à l’exception des applets)
doit contenir la méthode principale
« public static void main (args[]) ».
•
System.out.println() permet d’afficher un texte sur la sortie standard. Les chaînes de caractères peuvent
enchaînées à l’aide de « + ».
•
System.exit() termine le programme.
Version 1.0, 05.03.07
Page 2
Introduction à la programmation Java
Introduction
1.3 Développement de programme en Java
SUN met à disposition gratuitement sur son site (www.java.sun.com) le JDK (Java Development Kit), qui
contient les outils suivants :
javac : Java-Compiler, traduit le code source en code byte
java : exécute une application indépendante (stand alone)
applet viewer : exécute un applet
javadoc : génère une documentation à partir du code source
Tous ces outils doivent être démarrés à l’aide de lignes de commande. Par conséquent, on utilise souvent des
environnement de développement intégré (en anglais Integrated Development Environment et abrégé IDE), qui
sont basés sur le JDK et qui rassemblent tous les outils JDK dans un éditeur de texte et un débuggeur. Exemple :
JCreator, JBuilder, BlueJ etc.
1.3.1 Editeur de texte
Tous les éditeurs de texte sans instructions formatées peuvent être utilisé pour éditer le code source. Toutefois,
on utilise souvent des éditeurs qui mettent en évidence à l’aide de couleurs les structures du langage, les
commentaires etc.
1.3.2 Compilateur
Le compilateur Java traduit le code source dans le code byte, qui peut être exécuté sur toutes les plateformes. Le
code source est contrôlé pendant la compilation. Le code byte ne peut être généré, que s’il n’y a pas d’erreurs
dans le code source. Les fichiers contenant le code source ont une terminaison « .java » et les fichiers contenant
le code byte ont une terminaison « .class ».
Instruction pour démarrer le compilateur avec la ligne de commande :
javac
<filename>.java
Le compilateur génère ainsi le fichier suivant :
<filename>.class
1.3.3 Interpréteur
La machine virtuelle (en anglais Virtual Machine et abrégé par VM) interprète et exécute le code byte
intermédiaire. L’instruction « java » permet de démarrer la VM.
Instruction pour démarrer la machine virtuelle avec la ligne de commande :
java
<filename>
Version 1.0, 05.03.07
Page 3
Introduction
Introduction à la programmation Java
1.3.4 Vue d’ensemble
Le développement et l’exécution d’un programme Java s’effectuent schématiquement de la manière suivante :
Code source
Java
Editeur
<nomfichier>.java
Compilateur
Java
Code byte
Java
Browser avec
VM intégré
Système d’opération
avec VM
< nomfichier >.class
Chip VLSI avec VM
Hardware
(Ordinateur en réseau, console de jeux, téléphone mobile,
ustensile de ménage etc.)
Figure 1: Développement et exécution d’un programme Java
1.4 Les applications
Les applications Java sont des applications indépendantes et correspondent aux programmes standard, définis
avec des autres langages de programmation. Les applications Java nécessitent toutefois un interpréteur. Certaines
applications Java sont traduites avec un compilateur « juste à temps » (en anglais Just in Time). Le code généré
ainsi est plus rapide qu’un code interprété, mais n’est plus indépendant par rapport aux plateformes.
Le chapitre 1.2 contient un exemple d’application.
1.5 Les applets
Les applets peuvent être insérés dans les pages HTML et exécutés avec un explorateur Internet compatible Java.
Les applet sont des éléments actifs et tournent sur l’ordinateur de l’utilisateur en utilisant ses ressources. Ils
contiennent des éléments graphiques et se voient attribuer une surface par l’explorateur. Les applets peuvent
également être exécutés à l’aide d’un « visualiseur d’applet » (en anglais Applet-Viewer).
Le code suivant montre un applet, qui affiche le texte « I like Java » dans un cercle rouge :
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.*;
/**
* Class ExApplet - A simple applet
Version 1.0, 05.03.07
Page 4
Introduction à la programmation Java
Introduction
*
* @author FUE1
* @version 17.11.2003
*/
public class ExApplet extends Applet
{
// instance variables
private final String msg = "I like Java";
private Font font;
/**
* Called by the browser or applet viewer to inform this Applet that it
* has been loaded into the system. It is always called before the start
* method is called for the first time.
*/
public void init()
{
font = new Font("Helvetica", Font.BOLD, 32);
}
/**
* Returns information about this applet.
* @return a String representation of information about this Applet
*/
public String getAppletInfo()
{
// provide information about the applet
return "Title: First Applet \nAuthor: WBR1 \nA simple hello-applet ";
}
/**
* Draw the applet whenever necessary
* @param g
Reference to graphics system
*/
public void paint(Graphics g)
{
// draw red Circle
g.setColor(Color.red);
g.fillOval(10,10,300,300);
// set text
g.setColor(Color.black);
g.setFont(font);
g.drawString(msg,90,170);
}
}
Version 1.0, 05.03.07
Page 5
Introduction à la programmation Java
Introduction
L’applet peut être inséré dans une page HTML de la manière suivante :
<html>
<head>
<title>BspApplet Applet</title>
</head>
<body>
<h1>BspApplet Applet</h1>
<hr>
<applet code="BspApplet.class" width=320 height=320
</applet>
<hr>
</body>
</html>
Le démarrage de la page HTML dans l’explorateur Internet se traduit par l’affichage suivant :
Figure 2 : Notre applet
Version 1.0, 05.03.07
Page 6
Introduction à la programmation Java
Introduction
1.6 Avantages et désavantage du Java
Comme beaucoup de chose de la vie, Java ne possède pas que des avantages. Par conséquent, ce chapitre
énumère les avantages et les désavantages du langage de programmation.
Avantages
• Java est indépendant par rapport à la plateforme. Le même code peut fonctionner sur des plateformes
différentes sans qu’il ne doive être compilé à nouveau.
• Java contient beaucoup de fonctionnalité, qui sont définies dans le cadre du langage de programmation
(GUI, connexion Internet etc.). Dans les autres langages de programmation, ces fonctionnalités sont définies
dans des bibliothèques, qui ne sont pas toujours standardisées.
• Il existe beaucoup d’environnements de développement bon marchés pour Java.
• Java est un langage qui s’apprend facilement (en tous cas beaucoup plus simplement que C++)
• Certain prétendent que la productivité du développement en Java et meilleur que celle en C/C++ (Pas de
problématiques liées aux pointeurs, gestion de mémoire facilitée, et test d’exécution etc.).
Désavantages
• Le collecteur d’ordure (Garbage Collection) a pour tâche de libérer l’espace mémoire qui n’est plus utilisé.
Le code devient ainsi non déterministique, car le collecteur d’ordure, qui possède une grande priorité, peut
être appelé à tout moment. Cela ne constitue pas un problème dans le domaine de la programmation des
ordinateurs personnels. Par contre cela peut être catastrophique pour les applications temps réels. En
d’autres thermes, Java n’est pas recommandé pour les applications temps réels.
• Java est un langage interprété. Un interpréteur exécute le code toujours plus lentement qu’un programme en
code machine. Les programme Java sont donc toujours plus lent que les programmes C/C++. Les
compilateurs « juste à temps » permettent de résoudre ce problème, en générant un code objet.
• Java ne permet pas l’accès direct au hardware.
Remarque finale
Java est un langage de programmation moderne et puissant, qui possède des atouts dans le domaine de l’Internet.
Toutefois, java est relativement peu utilisé dans le domaine du temps réel. La VM fonctionne souvent comme
une tâche (anglais Task) sur un système d’opération temps réel. Les connexions Internet et les interfaces
graphiques sont souvent programmées en Java. Toutes les autres fonctionnalités, qui sont critiques en temps,
sont programmé en C/C++ et fonctionnent sous forme d’autres tâches, dont les priorités sont supérieures.
Version 1.0, 05.03.07
Page 7
Introduction à la programmation Java
Aspect procédural de la programmation Java
2 Aspect procédural de la programmation Java
2.1 Introduction
Java est un langage de programmation orienté objet. Toutefois, avant de commence avec la programmation
orienté objet, nous allons nous occuper des éléments procéduraux du langage de programmation Java (type de
données, structure de contrôle et les méthodes). Ces éléments sont très semblables à ceux du langage de
programmation C/C++. Le but de ce chapitre est de dresser la liste de ces éléments et de montrer les éventuelles
différences avec le langage de programmation C/C++.
Il est admis ici que le lecteur possède déjà une certaine connaissance du langage de programmation C.
2.2 Les éléments lexicographiques
2.2.1 Jeu de caractères
Java est un langage de programmation, qui est utilisé dans le monde entier. Pour cette raison, il utilise le jeu de
caractères Unicode. Ce jeu de caractère contient des nombreux caractères internationaux.
Un caractère Unicode est codé sur deux bytes. Les 128 premiers caractères sont identiques à ceux du code
ASCII. De plus, les 256 premiers caractères sont compatibles avec le jeu de caractères ISO-8859-1.
Un programme Java est composé essentiellement de caractères Unicode. Il est ainsi possible d’utiliser des
caractères spéciaux (comme par exemples é à è û etc.) pour constituer les noms symboliques.
2.2.2 Indicateur
Les indicateurs (identifier) sont des noms de variables, de méthodes, de classes et d’objets etc.
Les caractères suivants sont autorisés pour constituer un indicateur :
• Les majuscules et les minuscules (c. à d. qu’il existe une distinction entre les majuscules et les minuscules!)
• Les chiffres (0, 1, 2, 3, 4, 5, 6, 7, 8, 9). L’identificateur ne peut toutefois pas commencer avec un chiffre
• Le caractère de soulignement „_“
• Le caractère dollars „$“
• Tous les caractères Unicodes en dessus de 00C0
Exemples d’identificateurs autorisés :
JavaTools
Java_Tools
Java_3
Exemples d’identificateurs non autorisés :
Java-Tools
Java/Tools
3_Java
2.2.3 Les commentaires
Un bon code Java se distingue entre autre par la qualité des ces commentaires. Les commentaires simplifient la
recherche des erreurs et l’entretient du programme. Les nouveaux collaborateurs s’initient plus rapidement au
code.
Java met à disposition 3 sortes de commentaires
• Les commentaires en ligne
• Les commentaires en bloque
• Les commentaires de documentation
Version 1.0, 05.03.07
Page 8
Introduction à la programmation Java
Aspect procédural de la programmation Java
2.2.3.1 Les commentaires en ligne
Les commentaires en ligne permettent d’ajouter des remarques courtes au code. Ils permettent la définition d’un
commentaire jusqu’à la fin de la ligne. Les commentaire en ligne sont introduit avec « // » et terminent à la fin
de la ligne. Ce commentaire correspond à celui du C++.
Exemple :
// This is a ligne comment
int loop = 0;
// This is also a ligne comment
2.2.3.2 Les commentaire en bloque
Avec les commentaires en bloque, il est possible de commenter plusieurs lignes. Le commentaire de bloque est
enfermé entre les suites de caractères « /* » et « */ ». Mis à part *, tous les caractères sont admis après /*
(voir commentaire de documentation).
Exemple :
/* This is
a bloc comment
*/
2.2.3.3 Les commentaires de documentation
Les commentaires de documentation sont utilisés pour la génération de documentation automatique avec java
doc. Le commentaire de documentation est enfermé entre les suites de caractères « /** » et « */ ». javadoc
recherche la suite de caractère /** dans le code source afin de genèrer une documentation en foramt HTML.
Exemple:
/**
* Comment for the method
* @param p1 description of the first parameter
*/
public static void myFunc(int p1)
{
}
2.2.4 Les séquences d’échappement
Pour les caractères, qui ne peuvent pas être représentés, il existe les séquences d’échappement. C à d. que des
combinaisons spéciales de caractères sont mises à disposition pour représenter ces caractères. Ces dernières
commencent toujours avec « \ ».
Séquence
d’échappement
\b
\n
\r
\t
\f
\\
Description
Backspace
Linefeed
Carriage Return
Tabulateur horizontal
Formfeed
\
Séquence
d’échappement
\‘
\“
\u
\x
\oo
Description
‘
“
Caractère Unicode
Caractère hexadécimal
Caractère octal
Tableau 1 : Séquence d’échappement
Version 1.0, 05.03.07
Page 9
Introduction à la programmation Java
Aspect procédural de la programmation Java
2.3 Les mots clés
Java contient des mots clés, qui ne devraient pas être utilisés comme identificateur. Ces mots clés sont les
suivants :
Abstract
Assert
Boolean
Break
Byte
Case
Catch
Char
class
Const
Continue
Default
Do
double
else
extends
final
finally
float
for
goto
if
implements
import
instanceof
int
interface
long
native
new
package
private
protected
public
return
short
static
strictfp
Super
switch
synchronized
this
throw
throws
transient
try
void
volatile
while
Tableau 2 : Les mots clés de Java
En plus il existe les constantes littérales true et false pour les valeurs du type booléen ainsi que la constante
littérale null pour les références sur nulle part.
2.4 Les variables et le type de données élémentaires
Les variables servent pour stocker des données. Elles sont toujours typées, c. à d. que le type de la donnée à
stocker doit être défini à l’avance. Le type défini la taille de l’espace mémoire nécessaire au stockage de la
variable. Les variables sont adressées à l’aide de leur identificateur.
Java connaît 3 sortes de variables:
• Variable locale : Ces variables sont définies dans une méthode ou dans un bloque et existent uniquement
jusqu’à la fin du bloque, qui contient leur définition.
• Variable de classe : Ces variables sont définies dans une classe et existent indépendamment de l’objet, c. à
d. durant tout le déroulement du programme (voir chapitre Introduction à la POO avec Java).
• Variable d’objet : Ces variables sont également définies dans une classe. Elles sont créées lorsque qu’une
instance de la classe est créée et existent durant l’existence de cet objet (voir chapitre Introduction à la POO
avec Java).
2.4.1 Déclaration et initialisation de variable
Les variables sont déclarées de la manière suivante :
<type>
<ident>;
Dans la syntaxe de ci dessus <type> correspond au type de la variable. Cela peut être un type élémentaire ou une
classe (voir chapitre 2.4.2). <ident> représente l’identificateur de la variable.
Une variable peut être initialisé pendant la déclaration ou plus tard :
// Initialisation durung the declaration
int a = 1234;
// Initialisation after the declaration
int a;
a = 1234;
Version 1.0, 05.03.07
Page 10
Aspect procédural de la programmation Java
Introduction à la programmation Java
Contrairement à ANSI C, les variables peuvent être définie à n’importe quel endroit dans une méthode ou dans
un bloque (c. à d. qu’elles ne doivent pas obligatoirement être déclarée au début de la méthode ou du bloque).
2.4.2 Type de donnée élémentaire
Java distingue entre les types de données élémentaires et composés. Les types de données élémentaires (appelé
également simples ou primitifs) sont les nombres, les caractères ou les valeurs de vérité. Les types de données
composés sont les chaînes de caractères, les tableaux et les tableaux. Des types de données différents nécessitent
des bloques de mémoire différents. Ces types ressemblent à ceux du C/C++, mais il existe des différences
importantes :
•
•
•
La mémoire nécessaire au stockage des types de données élémentaires est définie indépendamment de la
plateforme par Java. Les problèmes concernant la grandeur du type, qui dépend de la plateforme, comme en
C, n’existent pas en Java.
Toutes les valeurs numériques sont signées. Les types de données non signés (unsigned) n’existent pas.
Tous les changements de type ne sont pas possibles, comme en C.
2.4.2.1 Les nombres entiers
Les nombres entiers sont précis et stockés de façon binaire en interne. Java contient les types de donnée entiers
et signés suivant :
Type
Byte
Short
Int
Long
Taille in bit
8
16
32
64
Domaine
-128 bis 127
-32768 bis 32767
-2'
147'
483'
648 bis +2'
147’483’647
-9'
223’372'
036'
854'
775'
808 bis
+9'
223’372'
036'
854'
775'
807
Exemple
byte b = 63;
short s = -4253;
int i = 523413241;
long l = -1234242L;
Tableau 3 : Nombre entier
Remarque concernant le type long: L’adjonction L ou l précise, qu’il s’agit d’un format long.
Les valeurs des nombres entiers peuvent être attribuées en décimal, hexadécimal ou en octal :
décimal: les valeurs sont attribuées normalement,
Ex. : int i = 123;
hexadécimal: les valeurs commencent avec "0x",
Ex. : int i = 0x234;
octal: les valeurs commencent avec "0",
Ex. : int i = 0123;
Ils existent des classes de wrapper pour tous les types de données élémentaires (voir chapitre POO). Ces classes
mettent à disposition les constantes MIN_VALUE et MAX_VALUE, qui spécifient les domaines de validité des
différents types. Ces classes possèdent le même nom que les types de données, mais leurs noms commencent
cependant avec une majuscule. Pour les entier ils existent les classes : Byte, Short, Integer et Long.
Exemple:
byte minByte = Byte.MIN_VALUE;
long maxLong = Long.MAX_VALUE;
Les classes de wrapper fournissent également des méthodes pour l’affichage des valeurs (transformation de la
valeur entière en chaîne de caractères). Ces méthodes sont les suivants :
toString(n)
toBinaryString(n)
toHexString(n)
toOctalString(n)
Version 1.0, 05.03.07
Transformation avec un système numérique décimal
Transformation avec un système numérique binaire
Transformation avec un système numérique hexadécimal
Transformation avec un système numérique octal
Page 11
Introduction à la programmation Java
Aspect procédural de la programmation Java
Exemple :
int i = 127;
System.out.println("Hexadecimal value: " + Integer.toHexString(i));
Affichage :
Hexadécimal value: 7F
2.4.2.2 Les nombres à virgule flottante
Les nombres à virgule flottante (ou les nombres réelle) sont stockés selon le format standard IEEE 754. Les
nombres à virgule flottante sont sujets aux erreurs de représentation. Plus spécifiquement, des erreurs d’arrondi
peuvent apparaître.
Les types de données suivants sont à disposition pour les nombres à virgule flottante.
Type
float
double
Grandeur en bit Domaine
32
+/- 1,4*E-45 bis 3,4*E38
Précision: 6 chiffres décimaux
64
+/- 4,9*E-324 bis 1,7*E308
Précision: 15 chiffres décimaux
Exemple
float fl = 123.0f;
float f2 = 1.23E2f;
double d1 = 1.4E2;
double d2 = 1.0d;
Tableau 4 : Les nombres à virgule flottante
Remarque : les nombres à virgule flottant doivent toujours être représentés avec un point devant la partie
fractionnaire. L’adjonction de f ou F avec le type float est obligatoire, alors que l’adjonction de d ou D avec
le type double est facultative. Les nombres sans adjonction seront interprétés comme double.
Ils existent également des classes de wrapper pour les nombres à virgule flottante (Float et Double), qui
spécifient également le domaine de validité de ces types (MIN_VALUE et MAX_VALUE).
2.4.2.3 Les caractères
En Java les caractères sont représentés à l’aide du Unicode (voir chapitre 2.2.1).
Type
char
Taille en bit
16
Domaine
Tous les caractères
Exemple
char c = '
a'
;
Tableau 5 : Les caractères
Important : Le type char correspond à 8 bit dans le langage de programmation C, alors qu’en Java il
correspond à 16 bits !
2.4.2.4 Les nombres booléens
Le type booléen est nécessaire pour les comparaisons. Les nombres booléen possèdent les valeurs true ou
false. Par conséquent, ce ne sont pas des nombres. Par ailleurs, le type booléen ne peut pas être changé dans
un autre type de données.
Type
boolean
Taille en bit
8
Domaine
true ou false
Exemple
boolean isReady = true;
Tableau 6 : Type booléen
Version 1.0, 05.03.07
Page 12
Introduction à la programmation Java
Aspect procédural de la programmation Java
Important: Dans le langage de programmation C, false est équivalent à une valeur zéro et true à une valeur
différente de zéro. Cela n’est pas le cas en Java ! Les conditions comme « if » (voire chapitre 2.9.2) nécessitent
une valeur booléenne. « if (1) » est correct en C mais faux en Java.
2.4.3 Les changements de type de données
Les changements de type de données (appelé également casting) permettent de changer un type de données dans
un autre type de données.
Syntaxe:
<Variable-Destination> = (Type de la Variable-Destination) <Variable-Source>
Exemple :
int i1, i2;
float f1
f1 = (float)i1 / (float)i2;
Ils existent deux sortes de changements de type de données :
Casting explicite : Le changement de type est défini explicitement par le programmeur.
Casting implicite : Le changement du type est exécuté implicitement par le compilateur.
Les changements de type de données peuvent mener à des effets de bord, qui ne sont pas souhaités, comme dans
l’exemple suivant :
byte b1;
short s1;
b1 = (byte) s1;
// Datenverlust des High-Byte, auf Risiko des Programmierers
Le tableau suivant contient une vue d’ensemble de tous les changements de type de données possibles. Le
tableau peut être interprété de la manière suivante :
Type de la partie de gauche = (cast nécessaire?) Type de la partie de droite
Type de la
partie de
gauche
Byte
Short
int
long
float
double
boolean
char
Type de la partie de droite
byte
short
cast
int
cast
cast
Long
Cast
Cast
Cast
float
cast
cast
cast
cast
double
cast
cast
cast
cast
cast
cast
cast
cast
Cast
cast
cast
boolean
char
cast
cast
Tableau 7 : Changement de type de données
:
cast :
:
opérateur de casting n’est pas nécessaire, attribution possible sans perte de donnée
opérateur de cast est nécessaire, possibilité de perdre des données
opération de casting n’est pas possible en Java
Version 1.0, 05.03.07
Page 13
Introduction à la programmation Java
Aspect procédural de la programmation Java
2.4.4 La visibilité
Les variables sont visibles dans un bloque (domaine entre « {} »), plus précisément depuis leur définition
jusqu’à la fin du bloque. Elles sont également visibles dans les sous bloque, de ce bloque.
Exemple:
public static void main(String args[])
{
int a = 1;
// a is only visible
{
int b = 2;
// a and b are visible
{
int c = 3;
// a, b and c are visible
}
// c in no more visible
}
// b in no more visible
}
2.4.5 Les variables globales
Les variables ne peuvent être définies qu’aux niveaux des méthodes et des classes (voir POO). Java ne connaît
pas de variables globales dans les sens de C. En échange, Java met à disposition les variables statiques de classe.
L’accès à ces derniers se fait indépendamment de toute instanciation d'
objet.
Exemple :
public class Global
{
static int myGlobal;
// global class variable
public static void main(String args[])
{
myGlobal = 7;
}
}
2.5 Les chaînes de caractères
Un string est un tableau de caractères (Unicode) et est utilisé pour stocker du texte. Les chaînes de caractères en
Java ne sont plus des types de données élémentaires mais des objets de classe String. Du fait que les strings
sont également nécessaires pour la programmation procédurale, le chapitre POO est un peu devancé à cet
endroit.
Java soutient deux classes pour le stockage des chaînes de caractères : String pour les chaînes de caractères
constantes et StringBuffer pour la création de chaîne de caractères.
2.5.1 String
Un objet String peut être défini de la manière suivante :
String student1 = "Hans";
String student2 = new String("Thomas");
Les méthodes, les plus importantes, qui peuvent être appliquées sur un objet String sont les suivantes :
int compareTo(String b):
Compare deux String. a.compareTo(b) fournit :
<0 si a est plus petit que b
Version 1.0, 05.03.07
Page 14
Introduction à la programmation Java
Aspect procédural de la programmation Java
= 0 si les deux String sont égaux.
<0 si a est plus grand que b
boolean equals(String b): Compare deux String. a.equals(b) fournit true, si a et b sont égaux
int length():
Fournit la longueur du String. a.length();
Les autres méthodes sont décrites sous « java.lang.String ».
Un String peut être copier dans un autre String avec l’opérateur « = » (ce qui n’était pas possible dans C !).
L’opérateur « + » permet d’enchaîner des String (par exemple pour des affichages).
Exemple:
public class StringTest
{
public static void main(String args[])
{
String student_1 = "John";
String student_2 = new String("Tom");
String student_3 = student_1;
System.out.println(student_1 + " " + student_2 + " " + student_3);
}
}
2.5.2 StringBuffer
La classe StringBuffer est mise à disposition pour la construction complexe de chaînes de caractères. Cette
classe contient des méthodes pour insérer ou ajouter des chaînes de caractères.
Les méthodes, les plus importantes, qui peuvent être appliquées sur un objet StringBuffer sont les
suivantes :
StringBuffer append(Type b): Ajoute une chaîne de caractères ou un type de données élémentaire
à la fin du tampon (buffer) existant.
StringBuffer insert(
Insère une chaîne de caractères ou un type de données élémentaires
à la position offset dans le tampon existant.
int offset, Type b):
int length():
Fournit la longueur du StringBuffer. a.length();
Un objet du type StringBuffer est créé à sa définition avec une longueur de 16 caractères. Cette longueur
sera agrandie dynamiquement en cas de nécessité.
Exemple:
public class StringBufferTest
{
public static void main(String args[])
{
int i = 7;
StringBuffer buffer = new StringBuffer();
buffer.append("John ");
buffer.append("Kennedy");
buffer.insert(3, i);
System.out.println("Contains of the buffer: " + buffer);
System.out.println("Length of the buffer: " + buffer.length());
}
}
Affichage du programme:
Contains of the buffer: Joh7n Kennedy
Length of the buffer: 13
Version 1.0, 05.03.07
Page 15
Introduction à la programmation Java
Aspect procédural de la programmation Java
2.6 Les tableaux
2.6.1 Les tableaux unidimensionnels
Les notions d’array, de tableau et de vecteur sont synonymes. Les tableaux servent à stocker des variables qui
ont le même type. Un élément est une cases du tableau et est accessible à l’aide de son indexe (ex.
myArray[2]). Le premier élément possède l’indexe 0.
Les tableau doivent toujours être déclarés, alloués et initialisées :
2.6.1.1 Déclaration du tableau
Le premier pas est la création d’une variable de référence pour adresser le tableau.
Syntaxe:
<Array type> <Array name> [];
Ou:
<Array type> [] <Array name>;
Exemple :
int intArray[];
boolean boolArray[];
Important: Les tableaux sont toujours gérés à l’aide de leur référence. Toutefois, la création de la variable de
référence n’alloue pas l’espace mémoire nécessaire au stockage des éléments du tableau.
2.6.1.2 Allocation du tableau
Le bloque de mémoire nécessaire au stockage des éléments du tableau est créé durant cette étape. Le nombre
d’élément n’est donc défini que durant l’exécution du programme, mais ce nombre ne peut plus être changé
après l’allocation. Les éléments sont initialisés durant l’allocation avec la valeur défaut (0). La taille de l’array
est fournit par la méthode lenght(), qui retourne son nombre d’éléments.
Syntaxe:
<Array name> = new <Array type>[<number of elements>];
Exemple :
intArray = new int [5];
boolArray = new boolean [10];
// allocate memory for 5 elements of type int,
// intArray is the reference, which address the array
// allocate memory for 10 elements of type boolean
Important : Les tableaux sont générés dynamiquement avec l’opérateur « new » durant l’exécution du
programme. Ils sont éliminés automatiquement par le collecteur d’ordure (Garbage Collection) à la fin du
programme. Dans C/C++, les programmeurs sont eux même responsables de la libération de l’espace mémoire
alloué aux différents objets. Dans Java, c’est le collecteur d’ordure qui reprend cette tâche. Il faut donc être très
prudent, lorsqu’on s’est habitué à Java et que l’on passe à la programmation en C/C++ !
La déclaration et l’allocation de tableau peuvent être effectuées en une seule étape.
Syntaxe:
<Array type> <Array name> [] = new <Array type>[<number of elements>];
Version 1.0, 05.03.07
Page 16
Introduction à la programmation Java
Aspect procédural de la programmation Java
2.6.1.3 Initialisation du tableau
Les éléments du tableau doivent être initialisés durant la dernière étape, si ces derniers doivent contenir une
valeur différente de 0. Cela est réalisé par attribution d’une valeur à chaque élément du tableau de la manière
suivante :
intArray[i] = wert;
Un tableau peut cependant être initialisé durant sa déclaration, comme cela est également le cas en C. La
déclaration, l’allocation et l’initialisation du tableau s’effectuent alors simultanément :
Syntaxe:
<Array type> <Array name> [] = {<value1>, <value2>, ..... , <valueN>};
Exemple :
int intArray [] = {1,2,3,4,5};
// allocate memory for 5 int elements and initialize them
Les valeurs attribuées peuvent également résulter d’un calcul, pourvu que ces dernières soient connues durant
l’attribution.
Exemple :
public class OneDimArray
{
public static void main(String args[])
{
int intArray[];
intArray = new int[2];
intArray[0] = 12;
intArray[1] = 17;
boolean boolArray[] = {true, false};
// Declaration
// Allocation
// Initialization
// Declaration, Allocation & Initialization
System.out.println("intArray[]: " + intArray[0] + " " + intArray[1]);
System.out.println("boolArray[]: " + boolArray[0] + " " + boolArray[1]);
}
}
2.6.1.4 Les erreurs d’indexages
Les erreurs d’indexage sont les erreurs qui apparaissent le plus souvent en C/C++ (dépassement de limites)
durant l’accès aux éléments d’un tableau. Cette erreur engendre la sur écriture des données, qui se situent dans
les environs du tableau dans la mémoire. Ces erreurs sont très difficiles à trouver, car les problèmes qu’ils
engendrent ne se situent pas en générale à l’endroit ou le code est en train d’être exécuté, mais à un tout autre
endroit.
En Java les erreurs d’indexage génèrent une exception du type :
« ArrayIndexOutOfBoundsException »
Exemple :
public class ArrayException
{
public static void main(String args[])
{
int intArray[];
intArray = new int[2];
intArray[0] = 12;
intArray[1] = 17;
// Declaration
// Allocation
// Initialization
System.out.println("intArray[2]: " + intArray[2]);
}
}
Version 1.0, 05.03.07
Page 17
Introduction à la programmation Java
Aspect procédural de la programmation Java
Dans la dernière instruction de cet exemple, un accès au 3ème éléments du tableau qui n’existe pas a lieu. Par
conséquent, le programme générera durant son exécution à cet endroit l’exception suivante :
ArrayIndexOutOfBoundsException: 2
2.6.2 Les tableaux multidimensionnelles
Java contient également les tableaux multidimensionnels. Ces derniers doivent être déclarés, alloués et
initialisés, comme ce fut le cas avec les tableaux unidimensionnelles.
Syntaxe pour les tableaux à deux dimensions :
<Array type> <Array name> [][];
<Array name> = new <Array type>[<number of rows>] [<number of columns>];
Ou :
<Array type> <Array name> [][] = new <Array type>[<number of rows>] [<number of columns>];
Accès aux différents éléments s’effectue de la manière suivante :
<Array name> [row][column] = <value>;
Ici la déclaration, l’allocation et l’initialisation peuvent également être effectuées en une seule étape :
<Array type> <Array name> [] [] = {
{<value11>, <value12>,.... ,<value1N>},
{<value21>, <value22>,.... ,<value2N>}
};
Exemple :
public class TwoDimdArray
{
public static void main(String args[])
{
int array1[][] = {{1,2,3},{10,11,12},{20,21,22}};
int array2[][] = {{100,101,102},{110,111,112},{120,121,122}};
int array3[][] = new int[3][3];
// Addition of the matrix array1 and array2, result into array3
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
array3[i][j] = array1[i][j] + array2[i][j];
System.out.print(array3[i][j] + " ");
}
System.out.println("");
}
}
}
2.7 Les constantes
Les constantes sont formées dans Java avec le mot clé final. final permet de définir et d’initialiser une
variable, qui ne peut plus être changée durant toute l’exécution du programme.
Exemple :
final float PI = 3.1415f;
Les constantes suivantes peuvent être formées :
• Les constantes entières, ex. :
final int i = 1234; final long l = 1234L;
•
Les constantes à virgule flottante, ex. : final float f = 1.23f; final double d = 1.23d;
•
Les constantes sous forme de caractère, ex. :
Version 1.0, 05.03.07
final char c = 'a';
Page 18
Aspect procédural de la programmation Java
Introduction à la programmation Java
•
Les constantes sous forme de chaîne de caractères, ex. : final String str = "Hello";
Important : L’instruction pour le preprocesseur #define, qui est supportée par C, ne peut pas être
utilisée en Java.
2.8 Les opérateurs
Dans Java comme en C/C++, une expression est l’unité minimale, qui peut être interprétés. Une expression
contient une ou plusieurs opérandes et au moins un opérateur, qui exécute un fonction sur les opérandes. Les
opérateurs unaires nécessitent un seul opérande, alors que les opérateurs binaires en nécessitent deux. Une
expression retourne toujours un résultat, dont le type dépend de l’opérateur et des opérandes.
Lorsqu’une expression contient plusieurs opérateurs, la priorité de ces derniers devient déterminante. La priorité
et l’associativité entre les opérateurs de priorité identique sont également définies dans Java :
Priorité
(précédence)
1 (le plus haut)
2
3
4
5
6
7
8
9
10
11
12
13
14
15 (le plus bas)
Opérateur
Complément
Associativité
[] . (params) expr++ expr-++expr --expr +expr -expr ~ !
new (type)expr
* / %
+ << >> >>>
< > <= >= instanceof
== !=
++,-- postfix
Gauche à droite
unair
Droite à gauche
Cast
Gauche à droite
binaire
Gauche à droite
Gauche à droite
Gauche à droite
Gauche à droite
&
Gauche à droite
^
Gauche à droite
|
Gauche à droite
&&
Gauche à droite
||
Gauche à droite
?:
Droite à gauche
= += -= *= /= %=
|= <<= >>= >>>=
&=
^=
Droite à gauche
Tableau 8 : Les opérateurs Java triés selon leur priorité
2.8.1 Les opérateurs arithmétiques
Les opérateurs arithmétiques nécessitent des opérandes numériques (en générale un opérateur de chaque côté de
l’opérateur). Le type du résultat correspond toujours au type de l’opérande, qui est le plus grand (par exemple :
une addition entre des opérande de types int et long fournit un résultat de type long).
Opérateur
- op1
op1 + op2
op1 – op2
op1 * op2
op1 / op2
op1 % op2
op1++
++op1
op1---op1
Désignation
Signe négatif
Addition
Soustraction
Multiplication
Division
Modulo
Post-incrément
Pre-increment
Post-décrément
Pre-dekcement
Description
Changement de signe
Somme de op1 et op2
Différence entre op1 et op2
Produit entre op1 et op2
Quotient entre op1 et op2
Reste de la division entière
Incrémenter op1 après exécution de l’instruction
Incrémenter op1 avant exécution de instruction
Décrémenter op1 après exécution de instruction
Décrémenter op1 avant exécution de instruction
Tableau 9 : Les opérateurs arithmétiques
Version 1.0, 05.03.07
Page 19
Introduction à la programmation Java
Aspect procédural de la programmation Java
Les opérateurs arithmétiques sont exécutés de gauche à droite en fonction des règles de priorité définies au
chapitre 2.8. Des parenthèses devraient être insérées en cas de doutes. Les parenthèses facilitent également la
compréhension du code.
L’écriture des opérateurs arithmétiques, qui sont combinés aux opérateurs d’affectation, peut être simplifiée (voir
chapitre 2.8.5).
2.8.2 Les opérateurs de comparaison
Les opérateurs de comparaison (appelé également opérateur relationnel) comparent deux opérandes numériques
ou deus expressions. Ils fournissent un résultat de type booléen.
Opérateur
op1 = = op2
op1 != op2
op1 < op2
op1 <= op2
op1 > op2
op1 >= op2
Désignation
Egalité
Inégalité
Plus petit
Plus petit ou égale
Plus grand
Plus grand ou égale
Description
Fournit true lorsque op1 est égal à op2.
Fournit true lorsque op1 n’est pas égal à op2.
Fournit true lorsque op1 est plus petit que op2.
Fournit true lorsque op1 est plus petit ou égal à op2.
Fournit true lorsque op1 est plus grand que op2.
Fournit true lorsque op1 est plus grand ou égal à op2.
Tableau 10 : Les opérateurs de comparaison
2.8.3 Les opérateurs logiques
Les opérateurs logiques permettent d’assembler des valeurs booléennes. Les opérandes et le résultat doivent
absolument avoir le type booléen :
Opérateur
!op1
op1 && op2
op1 || op2
Correspondance
NOT
AND
OR
Description
Fournit false lorsque op1 est true et inversement
Ne fournit true que lorsque op1 et op2 sont true
Fournit true lorsqu’au moins un opérateur est true
Tableau 11 : Les opérateurs logiques
Important: Avec l’opérateur « && », le résultat est false dès que l’opérateur de gauche l’est aussi. Dans ce cas la
condition de droit n’est pas testée. Avec l’opérateur « || », le résultat est true dès que celui de gauche l’est
aussi. Ici, la condition de droite n’est également pas testée.
2.8.4 Les opérateurs de traitement des bits
Les opérateurs de traitement des bits réalisent des manipulations au niveau des bits. Ils sont souvent utilisés pour
masquer des valeurs ou pour les déplacer de façon binaire. Les opérateurs doivent être entier.
Opérateur
~op1
op1 & op2
op1 | op2
op1 ^ op2
op1 << op2
Désignation
Complément à un
AND
OR
EXOR
Déplacement vers la gauche
op1 >> op2
Déplacement vers la droite
avec bit de signe
Version 1.0, 05.03.07
Description
Inverse tous les bits de l’opérande
Et binaire entre op1 et op2
Ou binaire entre op1 et op2
Ou exclusif binaire entre op1 et op2
op1 est déplacé de op2 bits vers la gauche.
Des bits « 0 » sont insérés depuis la droite.
op1 est déplacé de op2 bits vers la droite.
Des bits de signe sont insérés depuis la gauche.
Page 20
Aspect procédural de la programmation Java
Introduction à la programmation Java
op1 >>> op2
Déplacement vers la droite
avec bit « 0 »
op1 est déplacé de op2 bits vers la droite.
Des bits « 0 » sont insérés depuis la gauche.
Tableau 12 : Les opérateurs logiques binaires
Les opérateurs te traitement des bits ont été repris à partir du C/C++, le résultat de ces opérations correspondent
également à ceux du C/C++.
L’écriture des opérateurs te traitement des bits, qui sont combinés aux opérateurs d’affectation, peut être
simplifiée (voir chapitre 2.8.5).
2.8.5 Les opérateurs d’affectation
L’opérateur d’affectation attribue à l’opérateur de sa gauche la valeur de l’expression de sa droite. L’expression
de droite est ainsi évaluée avant l’affectation.
L’opérateur d’affectation peur être combiné avec des opérateurs arithmétiques, binaires et de traitement des bits,
afin de simplifier l’écriture.
Opérateur
op1 = <expr>
op1 += op2
op1 -= op2
op1 *= op2
op1 /= op2
op1 %= op2
op1 &= op2
op1 |= op2
op1 ^= op2
op1 <<= op2
op1 >>= op2
op1 >>>= op2
Désignation
Affectation
Affectation avec addition
Affectation avec soustraction
Affectation avec multiplication
Affectation avec division
Affectation avec modulo
Affectation avec AND binaire
Description
Attribue à op1 le résultat de l’expression de droite.
Attribue à op1 la somme de op1 + op2.
Attribue à op1 la différence op1 - op2.
Attribue à op1 le produit de op1 * op2.
Attribue à op1 le quotient de op1 / op2.
Attribue à op1 le reste de op1 % op2.
Attribue à op1 le résultat de l’opération binaire Et entre
op1 et op2.
Affectation avec OR binaire
Attribue à op1 le résultat de l’opération binaire Ou entre
op1 et op2.
Affectation avec EXOR binaire Attribue à op1 le résultat de l’opération binaire Ou
exclusif entre op1 et op2.
Affectation avec décalage vers Déplace op1 de op2 bits contre la gauche et stocke le
la gauche
résultat dans op1.
Affectation avec décalage vers Déplace op1 de op2 bits contre la droite, en duplifiant
la droite et dulcification du bit le bit de signe, et stocke le résultat dans op1.
de signe
Affectation avec décalage vers Déplace op1 de op2 bits contre la droit, en duplifiant le
la droite et dulcification du bit bit nulle, et stocke le résultat dans op1.
nul
Tableau 13 : Les opérateurs d’affectation
Remarque : Toutes les expressions du Tableau 13 retournent un résultat, qui est identique à celui attribué à op1.
Exemple:
int
int
int
op3
op1 = 5;
op2 = 8;
op3;
= (op1 += op2);
Fournit le résultat suivant:
op1 = op3 = 13
Version 1.0, 05.03.07
Page 21
Introduction à la programmation Java
Aspect procédural de la programmation Java
2.8.6 L’opérateur point d’interrogation
L’opérateur point d’interrogation est l’unique opérateur qui nécessite 3 opérandes.
Syntaxe:
expr1 ? expr2 : expr3
expr1 est une expression logique. Lorsque expr1 est true, l’opérateur retourne la valeur de l’expression
expr2. Par contre lorsque expr1 est false, ce dernier retourne la valeur de l’expression expr3. expr2 et
expr3 peuvent être de type booléen, numériques ou référence.
Exemple:
boolean BigSalary = (Salary > 10000) ? true : false;
L’opérateur point d’exclamation n’est rein d'
autre qu’une structure if-else (voir chapitre 2.9.2). Il est
essentiellement utilisé lorsque des notations compactes sont souhaitées, afin d’améliorer la compréhension du
code.
2.8.7 L’opérateur cast
L’opérateur cast permet de changer le type d’une expression A dans celui de l’expression B. Le casting a déjà été
traité dans le chapitre 2.4.3.
2.8.8 Les opérateurs supplémentaires pour la programmation OO
Java contient des opérateurs destinés à la programmation orientée objet. Ces derniers seront décrits plus en
détails dans la partie OO de cette documentation. Toutefois, ils sont introduits dans ce chapitre pour des raisons
de complémentarités.
Opérateur + pour enchaîner des chaînes de caractères
Si un des deux opérandes de l’expression « a + b » est un String, alors le résultat de cette expression est un
String composés. Par conséquent l’opérande, qui n’est pas un String avant l’enchaînement, sera changé en
String.
Les opérateurs = = et != pour les références
Ces opérateurs contrôlent, si deux références adressent le même objet ou pas. Toutefois, il n’y a pas de contrôle
en ce qui concerne le contenu des objets.
L’opérateur instanceof
L’opérateur instanceof permet de contrôler si un objet appartient à une classe ou pas. Ce contrôle peut être
effectué soit pendant la traduction ou durant l’exécution du programme (les objets ont des informations
supplémentaires durant exécution du programme (runtime information).
L’opérateur new
Les tableaux et les objets peuvent être créés avec l’opérateur new. L’opérateur new retourne une référence sur
l’objet, qui vient d’être instancié.
L’opérateur point
L’opérateur point permet l’accès aux variables et aux méthodes de classe et d’objet.
Version 1.0, 05.03.07
Page 22
Aspect procédural de la programmation Java
Introduction à la programmation Java
2.9 Les structures de contrôle
2.9.1 Introduction
Les structures de contrôle de Java sont identiques à celles de C/C++. Ces structures de contrôle permettent
d’influence le déroulement du programme en fonction des conditions. Les sous chapitres suivants traitent
brièvement ces structures de contrôle, à l’aide des structogrammes (Nassi-Shneidermann), des représentations
graphiques du type Backus-Naur, des brèves descriptions et des exemples.
2.9.2 L’instruction if
Syntaxe :
if(<Expression>)
{
<Instruction>;
}
else
{
<Instruction>;
}
Structogramme :
Expression
true
false
Instruction_1 Instruction_2
Forme graphique Backus-Naur :
if
(
Expression
)
Statement
else
Statement
Description :
if réalise une ramification du programme en fonction d’une condition. L’expression de la condition est évaluée
au début de la structure. Lorsque cette dernière fournit true, le programme exécute les instructions du bloque
if, dans ce cas contraire, il exécute les instructions du bloque else.
Exemple:
if(val < 0)
{
System.out.println("The value is negative");
}
else
{
System.out.println("The value is positive");
}
Remarque :
• La branche else peut être omise.
•
Les accolades peuvent être omises, lorsque le bloque if ou else ne contient qu’une instruction.
•
Les instructions if peuvent être emboîtées :
Version 1.0, 05.03.07
Page 23
Aspect procédural de la programmation Java
Introduction à la programmation Java
if(<Expression_1>)
{
if(<Expression_2>)
{
<Instruction>;
}
}
else
{
<Instruction>;
}
•
Des séries de conditions peuvent également être testées :
if(<Expression_1>)
<Instruction_1>;
else if(<Expression_2>)
<Instruction_2>;
else
<Default-Instruction>;
•
Contrairement à C/C++, la condition doit retourner impérativement un résultat du type booléen :
int value = Wert;
if(value) {}
if(value != 0) {}
// Error in Java, but correct in C
// correct
2.9.3 L’instruction switch
Syntaxe:
switch(<Expression>)
{
case <Constant_expression_1>:
<Instruction>;
break;
case <Constant_expression_2>:
<Instruction>;
break;
...
default:
<Instruction>;
}
Structogramme :
Expression
Const_1
Const_2
Instruction_1 Instruction _2
Default
...
Instruction
Forme graphique de Backus-Naur :
Version 1.0, 05.03.07
Page 24
Introduction à la programmation Java
switch
(
Aspect procédural de la programmation Java
Expression
)
{
}
case
:
Expression
default
:
Statement
Description :
switch réalise une ramification multiple en fonction d’une expression, qui est évaluée tout au début de
l’instruction. Le résultat de cette évaluation est alors comparé avec les valeurs des étiquettes « case ». Lorsqu’il
y a correspondance avec une de ces valeurs d’étiquette, toutes les instructions à partir de cette dernière sont alors
exécutées. Par conséquent le bloque d’instructions associé à une étiquette doit toujours se terminer avec
l’instruction break, afin d’empêcher l’exécution des instructions suivantes. Le bloque défaut est exécuté
lorsque aucune valeur d’étiquette ne correspond à celle de l’expression,
Exemple :
int value;
...
switch(value)
{
case (1): System.out.println("Value one"); break;
case (2): System.out.println("Value two"); break;
...
default: System.out.println("Value default");
}
Remarque :
• La partie défaut est en option. Le programme exécute aucune instruction, lorsqu’il n’y a pas de
correspondance entre la valeur d’une des étiquette et celle de l’expression.
• Plusieurs cas à traiter peuvent être rassemblés dans un groupe de différentes étiquettes. Les instructions à
exécuter sont alors définies après la dernière étiquette. Le « Fall through » devrait être toujours commenté !
Exemple :
case 'o': // Fall through
case 'O':
Sysetm.out.println("Caractère o ou O");
break;
•
Le type de l’expression de switch et les types des constantes des étiquettes case doivent être entiers,
comme par exemple byte, char, short ou int. Les comparaisons avec d’autres types ne sont pas
possibles.
2.9.4 La boucle while
Syntaxe :
while(<Expression>)
{
<Instruction>;
}
Structogramme :
Version 1.0, 05.03.07
Page 25
Aspect procédural de la programmation Java
Introduction à la programmation Java
while (Expression)
Instruction
Forme graphique de Backus-Naur :
(
while
Expression
Statement
)
Description:
while est une boucle, où la condition est évaluée à son début. Lorsque cette dernière est true, le programme
exécute les instructions du corps de la boucle. Il s’en suit une réévaluation de la condition. Le corps de la boucle
while est ainsi exécuté jusqu’à ce que la condition de départ devienne false.
Exemple:
int i = 0;
while( i < 10)
{
System.out.println("i = " + i);
i++;
}
L’instruction println() est exécutée 10 fois dans cet exemple (i = 0 jusqu’à et avec i = 9)
Remarque :
• Aucune instruction n’est exécutée, lorsque la condition est false dès le départ.
• La condition à évaluer doit impérativement retourner un résultat du type booléen!
• La valeur de la condition doit être modifiée impérativement dans la boucle. Si non la boucle devient infini.
• Les boucles while peuvent être emboîtées.
• Les accolades peuvent être omises, lorsqu’une seule instruction est contenue dans le corps de la boucle.
2.9.5 La boucle do while
Syntaxe :
do
{
<Instruction>;
} while(<Expression>);
Structogramme:
do
Instruction
while (Expression)
Forme graphique de Backus-Naur :
do
Version 1.0, 05.03.07
Statement
while
(
Expression
)
;
Page 26
Aspect procédural de la programmation Java
Introduction à la programmation Java
Description:
do-while est une boucle, où la condition est évaluée à sa fin. Le bloque contenant les instructions est exécuté
une première fois. Ensuite le programme évalue la condition. Lorsque cette dernière est true, le programme
exécute de nouveau les instructions du corps de la boucle. Il s’en suit une réévaluation de la condition. Le corps
de la boucle do-while est ainsi exécuté jusqu’à ce que la condition à sa fin devienne false.
Exemple:
int i = 0;
do
{
System.out.println("i = " + i);
i++;
} while( i < 10);
L’instruction println() est exécutée également 10 fois dans cet exemple (i = 0 jusqu’à et avec i = 9)
Remarque :
• En comparaison avec la boucle while, le bloque des instructions de la boucle do-while est toujours
exécuté au moins une fois.
• La condition à évaluer doit impérativement retourner un résultat du type booléen !
• La valeur de la condition doit être modifiée impérativement dans la boucle. Si non la boucle devient infini.
• Les boucles do-while peuvent être emboîtées.
• Les accolades peuvent être omises, lorsqu’une seule instruction est contenue dans le corps de la boucle.
2.9.6 La boucle for
Syntaxe :
for(<Expression_1>; <Expression_2>; <Expression_2>)
{
<Instruction>;
}
Structogramme :
for (Expression_1; Expression_2; Expression_3)
Instruction
Forme graphique de Backus-Naur :
for
(
Expression
;
Expression
;
Expression
Variable
declaration
)
Statement
Description:
La variable de boucle est initialisée tout au début à l’aide de l’expression « Expression_1 ». En Java il est
également possible de définir cette variable à cet endroit. Il s’en suit l’évaluation de la condition fournie par
l’expression « Expression_2 ». Lorsque cette dernière est true, le programme exécute les instructions du
corps de la boucle et évalue ensuite l’expression « Expression_3 ». Normalement cette dernière est utilisée
Version 1.0, 05.03.07
Page 27
Introduction à la programmation Java
Aspect procédural de la programmation Java
pour incrémenter la variable de boucle. Le corps et les instructions d’itération de la boucle for sont ainsi
exécutés jusqu’à ce que la condition dans Expression_2 devienne false.
Exemple:
for(int i = 0; i < 10; i += 2)
{
System.out.println("i = " + i);
}
L’instruction println() est exécutée 5 fois dans cet exemple ( i = 0, 2, 4, 6 et 8)
Remarque :
• Lorsque la variable de boucle est déclarée en interne de la boucle, sa visibilité se limite à cette dernière
• Les accolades peuvent être omises, lorsqu’une seule instruction est contenue dans le corps de la boucle.
• La condition à évaluer doit impérativement retourner un résultat du type booléen !
• La boucle for peut être remplacée par une boucle while de la manière suivante :
<Expression_1>;
while(<Expression_2>)
{
<Instruction>;
< Expression_3>;
}
•
Certaines expressions de la boucle for peuvent être omises (Expression_1; Expression_2; Expression_2).
Toutefois les points-virgules doivent absolument rester. Exemple :
for( ; i < 10; ) { }
•
// i ist not initialised and not modified!
Les boucles for peuvent être emboîtées.
2.9.7 Contrôle des boucles avec les instructions break et continue
L’instruction break a été introduite ci-dessus avec les ramifications switch, pour terminer les étiquettes
case. Dans ce cas break est vivement recommandé.
break et continue sont des instructions, qui permettent d’influencer le déroulement des boucles.
L’utilisation de ces instruction est considéré comme un très mauvais style de programmation (visibilité et
entretient réduits). Cependant dans certain cas, l’application de ces instructions peut s’avérer très utile (par
exemple pour réduire la profondeur d’un emboîtement). Mais, le code devrait être bien commenté dans ces cas.
2.9.7.1 L’instruction break
L’instruction break permet de quitte une boucle, indépendamment de la condition d’arrêt de la boucle. Les
instructions du corps de la boucle qui suivent break ne sont ainsi plus exécutées.
Lorsque les boucles sont emboîtées l’une dans l’autre, seule la dernière boucle est quittée, réduisant ainsi
l’emboîtement de 1.
Théoriquement l’instruction break peut également mener à un label. Ce qui permet de quitter des boucles
emboîtées l’une dans l’autre d’un seul coup et ce qui correspond à l’instruction goto du C.
L’instruction break ne devrait être utilisé de manière réservée (en combinaison avec une instruction if).
Exemple:
int array[] = new int[10];
... // read the array
// search if the array contains the value 55:
for(int i = 0; i < array.length; i++) //
{
if(array[i] = = 55)
{
System.out.println("got it");
Version 1.0, 05.03.07
Page 28
Introduction à la programmation Java
Aspect procédural de la programmation Java
break; // the search operation ends here, if the value 55 has been found!
}
System.out.println(array[i]);
}
2.9.7.2 L’instruction continue
L’instruction continue permet de quitter le corps de la boucle, sans exécuter les instructions suivantes.
Contrairement à l’instruction break, la boucle n’est pas quittée, mais le programme continue avec l’évaluation
d’une nouvelle condition. Dans le cadre des boucles for, les variables de boucles qui sont modifiées avant
l’évaluation de la condition.
L’instruction continue devrait également être exécuté de manière réservée (combiné avec une instruction if).
L’instruction continue permet aussi des sauts sur des labels. Ce qui permet de quitter les boucles emboîtées.
Exemple: éviter la division par zéro
int array[] = new int[10];
... // read the array
// Display the inverse of the element values :
for(int i = 0; i < array.length; i++) //
{
if(array[i] = = 0)
{
System.out.println("Element is 0 ");
continue; // the inverse of 0 should not be computed!
}
System.out.println("Inverse of " + array[i] + "is: " + (1 / array[i]));
}
2.10 Les méthodes
2.10.1 Nom, Liste de paramètres et valeur de restitution
Java contient fondamentalement des méthodes de classe et d’objet. Le chapitre 3 « Introduction à la POO avec
Java » traitera ce sujet plus en détails. Ce chapitre ne traite que les méthodes (statique) de classe. En Java il est
possible de programmer de façon purement procédurale avec les méthodes statiques.
Les méthodes statiques du Java ont les mêmes propriétés que les fonctions de C. Toutefois, les méthodes
appartiennent toujours à une classe et, par conséquent, elles ne peuvent pas être définies en dehors des classes.
Le code, qui doit être exécuté plusieurs fois, peut être ainsi rassemblé dans une méthode. Ces méthodes peuvent
être appelé depuis des autres méthodes et elles peuvent également s’appeler elle-même (récursion). Les
méthodes procurent une structure claire et modulaire au programme. Le code devient ainsi plus facile à tester à
modifier et à entretenir.
Syntaxe pour la définition d’une méthode :
modifier restitution_type method_name (parameter_list)
{
// Instructions of the method
}
Propriétés des méthodes
• L’entête de la méthode définie son interface. Les méthodes appelantes doivent se tenir à cette interface.
• Le modificateur (modifier) spécifie la visibilité de la méthode. Le mot clé « static » peur être ajouter à
cet endroit, pour indiquer que la méthode est statique.
• Le type de restitution indique le type de la valeur qui sera retourné par la méthode. Cette valeur est fournie à
la fin de la méthode avec l’instruction « return ». La valeur de restitution est utilisée pour communiquer
le résultat d’un calcul ou des message d’erreur. Le chapitre Exception Handling traitera des autres
techniques de traitement d’erreurs. Une seule valeur peut être restituée au maximum. Le type de restitution
« void » indique que la méthode ne retourne pas de paramètres. Les valeurs de restitution peuvent être des
Version 1.0, 05.03.07
Page 29
Introduction à la programmation Java
•
•
•
•
Aspect procédural de la programmation Java
données de type élémentaire, des tableaux et des objets créés à partir des classes. Les données de type
élémentaire sont retournées « by value » alors que les tableaux et les objets sont retournés « by reference ».
Le nom de la méthode sert à son identification. Le nom symbolique de la méthode doit respecter les règles
qui régissent la composition des identificateurs introduites au chapitre 2.2.2.
La liste des paramètres permet de transmettre des valeurs aux méthodes. Cette liste doit contenir les types et
les noms de tous les paramètres, qui sont visibles dans tout le corps de la méthode. Les paramètres peuvent
être des données de type élémentaire, des tableaux et des objets créés à partir des classes. La transmission
des paramètres de type élémentaire s’effectue par valeur (by value). C. à d. que des copies des paramètres
sont transmises à la méthode. La méthode peut ainsi modifier les paramètres sans que leur valeur originale
ne soit affectée. Toutefois, Java ne permet pas une transmission par référence des données de type
élémentaire, comme en C. Lorsque aucun paramètre n’est transmis à la méthode, la paire de parenthèse de
l’entête doit être vide.
Le corps de la méthode entre les accolades, contient une suite de définitions de variable et d’instructions.
Les variables, qui sont définies dans une méthode, ne sont visibles que dans cette méthode. Plus
précisément, les variable ne sont visible qu’à partir de leur définition jusqu’à la fin de la méthode, ou
respectivement du bloque, qui contient leur définition. Toutes les variables locales ne sont plus valables à
partir du moment ou le programme quitte la méthode. Les variables qui ont été créé dynamiquement sont
détruisent par le collecteur d’ordure (Garbage Collection).
L’ordre de la définition des méthodes dans une classe est libre. La définition de prototype pour les méthodes
n’est par conséquent pas nécessaire. Java n’a ainsi pas besoin des fichier d’entête (Header) ou d’insertion
(Includes) comme en C/C++.
Exemple:
public class Methodes_1
{
static final float PI = 3.1415f;
/**
* Example for call by value and return of a value
* computeAreaCircle() computes the area of a Circle
*/
static float computeAreaCircle (float r)
{
return(r*r*PI);
}
/**
* Example for call by reference
* clearArray() clear all elements of an array
*/
static void clearArray (int array[])
{
for(int i = 0; i < array.length; i++)
{
array[i] = 0;
}
}
/**
* Example for return of a reference
* createBooleanArray creates a Boolean array and
* returns the reference of this array.
*/
static boolean []createBooleanArray ()
{
boolean bool[] = new boolean[3];
bool[0] = true; bool[1] = true; bool[2] = false;
return(bool);
}
/**
* Main programm
*/
Version 1.0, 05.03.07
Page 30
Introduction à la programmation Java
Aspect procédural de la programmation Java
public static void main(String[] args)
{
// Test: call by value and return of a value
float r = 2.12f;
// Radius of the Circle
float f;
// Area of the Circle
f = computeAreaCircle (r);
System.out.println("Radius = " + r + " ; area Circle = " + f);
// Test: call by reference
int intArray[] = {1, 6, 83};
// Originale array
clearArray(intArray);
System.out.print("Int array: ");
for(int i = 0; i < intArray.length; i++)
System.out.print(intArray[i] + " ");
System.out.println("");
// Test: return of a reference
boolean booleanArray[];
booleanArray = createBooleanArray ();
System.out.print("Boolean array: ");
for(int i = 0; i < booleanArray.length; i++)
System.out.print(booleanArray [i] + " ");
System.out.println("");
}
}
Affichage sur l’écran:
Radius = 2.12 ; area Circle = 14.119156
Int array: 0 0 0
Boolean array: true true false
2.10.2 Signature, prototype et sur chargement (overloading)
La notion de signature d’une méthode représente son nom et sa liste des paramètres. Exemple :
funcName (int, int). Ici, la liste des paramètres ne doit pas obligatoirement contenir les noms des
paramètres.
La notion de prototype d’une méthode représente sa signature et son type de restitution. Exemple :
public static void funcName (int, int).
Les méthodes avec des noms similaires mais avec des listes de paramètres différentes ont des signatures
différentes. Ces méthodes sont considérées comme différentes et cette distinction est qualifiée de sur
chargement (overloading). Java a repris le concept de sur chargement du C++.
L’application du concept de sur chargement est très utile avec des méthodes, qui réalisent la même tâche avec
des paramètres différents, comme par exemple le calcul du maximum :
public class Overloading
{
static int max(int i, int j)
{
System.out.println("Call off int max (int, int)");
return(i > j) ? i : j;
}
static long max(long i, long j)
{
System.out.println("Call off long max (long, long)");
return(i > j) ? i : j;
}
Version 1.0, 05.03.07
Page 31
Introduction à la programmation Java
Aspect procédural de la programmation Java
public static void main(String[] args)
{
int a1 = 1, a2 = 2, max_int;
long b1 = 22L, b2 = 33L, max_long;
max_int = max(a1, a2);
// Call the method int max(int, int)
max_long = max(b1, b2);
// Call the method long max(long, long)
System.out.println("max_int = " + max_int + " max_long = " + max_long);
}
}
Remarque : La définition de la méthode « static long max (int i, int j) » gégène dans cet
exemple un message d’erreur, car cette dernière a la même signature que la méthode
« statique int max (int i, int j) ».
2.10.3 La récursion
La récursion ou l’appel récursif signifie qu’une méthode s’appelle elle-même. Les variables locales sont de
nouveau créées et initialisées à chaque appel récursif. Il est très important de définir un critère d’arrêt atteignable
pour la récursion !
Une approche récursive est intéressante lorsqu’un problème peut être divisés en sous problèmes, dont la solution
est identique à celle du problème principale (exemple : calcul de la faculté d’un nombre). Le critère arrêt est très
important ici, si non la solution du problème nécessiterait plus de mémoire que celle mises à disposition par
l’ordinateur ou le programme entrerait dans une boucle infinie ! Il existe toujours des solutions non récursives
pour des problèmes récursifs.
Remarque : Il faut faire très attention avec les approches récursives ! Dans certain l’approche non récursive est
préférable, même si cette dernière n’apparaît pas comme étant très élégante. Les approches récursives sont
interdites dans les applications, où la sécurité est très importante !
Exemple : Le calcul du plus grand diviseur en commun (Greatest Commun Divider : gcd) avec
l’algorithme d’Euclide :
public class Euclid
{
static int gcd(int a, int b)
{
if(b != 0)
return(gcd(b, a%b));
return(a);
}
// Test the break criteria
// recursive call, gcd() calls herself
public static void main(String args[])
{
int a, b, res;
a = Integer.parseInt(args[0]);
b = Integer.parseInt(args[1]);
res = gct (a, b);
System.out.println("gcd of " + a + " and " + b + " is: " + res);
}
}
2.11 La méthode principale main()
Des paramètres peuvent être transmis au programme à son démarrage :
java <Programmname> <Parameter_1> <Parameter_2> .... <Parameter_n>
Les paramètres sont séparés par des espaces.
Version 1.0, 05.03.07
Page 32
Introduction à la programmation Java
Aspect procédural de la programmation Java
Chaque programme Java possède une méthode principale main(), qui est appelé au démarrage de dernier. Le
nom de la classe contenant main() doit être identique à celui du programme. La méthode main() possède le
prototype suivant :
public statique void main(String args[]).
Les paramètres introduits par l’utilisateur sont transmis à la méthode main() à l’aide d’un tableau de String.
L’accès séparé aux paramètres s’effectue ainsi à l’aide de args[i]. Contrairement à C/C++, dans Java
args[0] ne contient pas le nom de la fonction mais le premier paramètre ! Le deuxième paramètre est transmis
par conséquent avec args[1] etc. Les paramètres sont toujours transmis sous forme de String. Des
changements sont donc nécessaires de temps en temps, comme par exemple lorsqu’un paramètre doit être
interprété comme entier : int parameter_1 = Integer.parseInt(args[1]); args.length
fournit le nombre de paramètres, qui ont été tranmis à la méthode main(). Il est recommandé de toujours
contrôler le nombre des paramètres, qui sont fournis au programme, et de générer éventuellement des messages
d’erreurs.
Exemple :
public class MainArgs
{
public static void main(String[] args)
{
for(int i = 0; i < args.length; i++)
{
System.out.println("Parameter args[" + i + "] =" + args[i]);
}
}
}
Lorsque le programme est appelé de la manière suivante :
java MainArgs Hallo 2
Les objets suivants sont affichés dans ce cas sur l’écran :
Parameter args[0] = Hallo
Parameter args[1] = 2
Version 1.0, 05.03.07
Page 33
Introduction à la programmation Java
Introduction à la POO avec Java
3 Introduction à la POO avec Java
3.1 Introduction
Aujourd’hui il existe deux groupes de langage de programmation :
1) Les langage de programmation fonctionnel ou procédural (C, Pascal, Fortran etc.) : L’aspect principale de
ces langages de programmation est le déroulement fonctionnel. Le programme est ainsi exécuté de manière
Top-Down. Les données sont également importantes, mais elles sont considérées de manière secondaire, par
rapport au déroulement fonctionnel.
2) Les langages de programmation orienté objet (Java, C++, Smalltalk etc.) : Ici on essaye de modéliser la
réalité à l’aide d’objets. Les langages de programmation orienté objet soutiennent beaucoup plus cet
demande que les langages de programmation procédural.
Exemple:
Dans une application graphique il faut dessiner des cercles.
Avec les langages de programmation fonctionnels, il faudrait définir des variables pour le rayon, le centre et peut
être même la couleur des cercles. Idéalement, toutes ces données devraient être rassemblées dans une structure.
Ensuite, il faudrait définir les fonctions pour dessiner ou déplacer ces cercles sur l’écran. Ainsi, les données des
cercles seraient transmises à ces fonctions afin de les représenter sur l’écran. Toutefois, dans cet aspect du
traitement du problème, il manque une structure qui rassemble les fonctions et les données en une seule entité.
Un deuxième pas serait l’application des types de donnée abstrait (voire chapitre 3.1.2). Ici les données des
cercles seraient protégées par rapport à l’extérieur et des fonctions seraient mis à disposition pour modifier ces
données (ex. setRadius() etc.). Cet aspect est relativement bon, mais n’est quasi pas soutenu par les langages de
programmation procédurale
Avec les langages de programmation orientée objet, une classe Circle serait définie. Une classe est en quelque
sorte un plan de construction, qui définit ce qu’un objet possède et peut faire. Cette classe serait capable de gérer
les données du cercle, qui seraient protégées de l’extérieur, et fournirait toutes les fonctions (dans les langages de
programmation OO on parle de méthode) pour traiter ces données. Ainsi, il serait possible de créer plusieurs
objets de cette classe (c. à d. que sous un aspect software, des objets « vivants » sont créés en fonction du plan de
construction). L’utilisateur du programme pourrait ainsi dessiner plusieurs cercles, qui seraient tous des objets de
la classe cercle avec toutefois des rayons et des couleurs différents.
Ce qui a été introduit brièvement dans cet exemple, sera traité de manière détaillée dans ce chapitre.
3.1.1 Les problèmes des langage de programmation procédural
Avec des langages de programmation procédural conventionnel, les problèmes suivants apparaissent avec le
développement de gros projets, qui doivent être entretenus et complétés au cours du temps :
1) Les structures de donnée sont définies de manière globale. Les fonctions qui ont accès à ces structures de
donnée sont en générale répartie dans tous les modules du programme. Si une structure de donnée doit être
adaptée, toutes les fonctions qui ont accès à cette structure de donnée doivent également être modifiées.
2) Les nouvelles fonctionnalités, qui doivent être ajoutées au programme et qui sont identiques à des fonctions
préexistantes, seront toujours insérées au code par des opérations copie et adaptation. Ces nouvelles
fonctions doivent systématiquement être testées et le programme devient de plus en plus redondant. De plus,
si une erreur est découverte dans une fonction « d’origine » du code, il faudra corriger toutes les fonctions
qui ont été définie à partir de cette fonction.
3.1.2 Les types de donnée abstraits
Les types de données abstraites (ADT, Abstract Data Types) peuvent également être utilisé avec des langages de
programmation procédurale. La principale caractéristique de ces types de donnée est la séparation de l’interface
par rapport à l’implémentation.
Version 1.0, 05.03.07
Page 34
Introduction à la programmation Java
Introduction à la POO avec Java
Fondamentalement la structure des types de données abstraites est la suivante :
• Donnée: La structure de donnée est seulement connue à l’intérieur de l’ADT, et est masquée par rapport à
l’extérieur (information hiding).
• Méthode: Les méthodes traitent les données. L’utilisateur ne peut accéder aux données internes qu’avec ces
méthodes.
La modernisation du programme et l’encapsulement des données peuvent être effectué proprement à l’aide des
ADT. Les changements de code sont ainsi possibles par adaptation de la structure de donnée et des méthodes qui
traitent ces dernières, à l’intérieur de l’ADT. Tant que l’interface de l’ADT reste identique, le programme ne doit
pas être changé à des autres endroits. Le changement se limite ainsi uniquement à l’ADT.
Comme ce fut déjà mentionné dans ce document, les langages de programmation fonctionnelle ne soutiennent
presque pas les ADT.
3.1.3 Exigences pour les langage de programmation OO
A partir des connaissances de ci-dessus, les demandes suivantes peuvent être formulées pour les langages de
programmation OO :
1) Il faut pouvoir définir des « types de donnée » orientés problèmes. Les données et les méthode des ces
derniers doivent former une entité.
2) Les structures des données internes ne doivent être accessible qu’en cas de nécessité. Dans les autres cas,
ces dernières devraient être protégées.
3) Uniquement les interfaces des méthodes doivent être visibles de dehors. Leurs implémentations doivent être
masquées.
4) Les parties du code, qui sont communes, doivent pouvoir être isolées.
5) Des techniques de changement de code préexistant doivent être mises à disposition.
3.2 Caractéristiques des langages OO
Le but de la programmation OO est de reproduire le monde réel à l’aide d’objets. Ces derniers peuvent être des
plantes, des animaux, des hommes, des machines, des véhicules etc. La plupart de ces objets ont des propriétés
communes et des relations avec d’autres objets. Il en résulte une forme d’hiérarchie d’objets (par ex. un cercle et
un rectangle sont des objets géométriques, qui ont des coordonnées et des couleurs).
La programmation OO est basée sur les principes suivants :
• Abstraction
• Encapsulation
• Héritage et polymorphisme
3.2.1 Abstraction à l’aide d’objet
Le programmeur va essayer de reproduire la réalité avec des objets appropriés dans son programme. Cette
affirmation est basée sur le mot « essayer », car ce pas peut être très difficile et demande beaucoup d’expérience
avec les problèmes complexes.
Un objet représente une unité software. Il contient des attributs et des méthodes :
Les attributs sont les éléments variables d’un objet. Ils peuvent être changés pendant la durée de vie de l’objet.
Typiquement, les attribut peuvent être: la grandeur, la longueur, le poids, la couleur, la vitesse etc. Les attributs
peuvent également être des objets : comme par exemple un cercle possède un attribut point central, qui est objet
point).
Les méthodes sont les fonctions, qui peuvent être exécutées sur ces objets. Par conséquent, ils définissent le
comportement d’un objet. Typiquement les méthodes peuvent être, additionner, soustraire, mettre à 1, démarrer,
dessiner, rouler etc.
Exemple objet Circle :
Version 1.0, 05.03.07
Page 35
Introduction à la programmation Java
Introduction à la POO avec Java
Attribut : x_coord, y_coord, radius, isVisible etc.
Méthode : setCoord(), draw(), move() etc.
Plusieurs cercles « vivants » peuvent être gérés par le programme. Ces derniers ont tous les mêmes attributs et
les mêmes méthodes. Toutefois, les valeurs des attributs peuvent être différentes. Le cercle 1 peut par exemple
avoir un autre rayon et des autres coordonnées que le cercle 2. Si l’utilisateur du programme graphique souhaite
dessiner un nouveau cercle, le programme génère dans un premier temps un nouveau objet du type cercle,
ensuite il défini le centre et le rayon de ce cercle et finalement il appelle la méthode « draw() » afin d’afficher
le cercle sur l’écran.
x_coord
y_coord
radius
isVisible
Programm
setCoord()
draw()
move()
Cercle
3
r = 5
Cercle
1
r = 4
Ecran
Cercle
2
r = 10
Figure 1 : Objets du type cercle
Les objets seront traités plus en détail au chapitre 3.3.
3.2.2 Encapsulation
Les attributs d’un objet ne sont normalement pas visibles à l’extérieur de l’objet. Ils ne peuvent être modifiés que
par des méthode, qui sont mises à disposition par l’objet lui même. Par ailleurs, seul l’interface des méthodes est
connue et leurs implémentations restent masquée. Par conséquent, la structure interne des données et
l’implémentation des méthodes de l’objet peut être modifiées, sans devoir changer les séquences de codes en
relation avec l’objet. Naturellement, la condition pour cela est que les interfaces des méthodes restent
inchangées.
Exemple: La méthode calculate() pour l’exécution d’un algorithme complexe doit être améliorée. La méthode et
les types de donnée des attributs peuvent ainsi être réadaptés, sans qu’il y ait des conséquences sur les autres
parties du programme.
Remarque: Le concept de l’encapsulation des données permet d’une part d’augmenter la sécurité des
données et d’autre part de faciliter les changements ultérieurs du programme.
3.2.3 Héritage et polymorphisme
Le but de l’héritage est la recherche de similitude entre différents objets pour définir une hiérarchie des objets.
Les parties similaires du code peuvent ainsi être rassemblées, afin de réduire la redondance du programme.
Ainsi, des nouveaux objets pourront être définis à partir d’objets déjà existants.
L’exemple des objets géométriques Circle et Rectangle, qui a été introduit au début de ce chapitre, peut
être utilisé ici pour illustrer le principe d’héritage et de polymorphisme. Pour résoudre ce problème de manière
Version 1.0, 05.03.07
Page 36
Introduction à la programmation Java
Introduction à la POO avec Java
structurée, il faut définir au départ un objet géométrique avec les attributs coordonnées (X et Y) et isVisible,
qui permet de dernier la visibilité de l’objet sur l’écran. L’objet géométrique sert d’objet de base pour les objets
dérivés Circle et Rectangle, qui héritent les caractéristiques de l’objet géométrique (attributs et
méthodes). Ainsi Circle possède déjà les coordonnées x_coord et y_coord, qui sont complétés par son
rayon. Le rectangle hérite également les coordonnées, qui sont complétés par sa largeur et sa hauteur.
Objet géométrique
x_coord
y_coord
isVisisble
Cercle
radius
Rectangle
width
height
Figure 2 : Hiérarchie des objets graphiques
Les méthodes ont été omises dans cette figure. Ainsi, Circle possède, en complément de son attribut radius,
les attributs x_coord, y_coord et isVisible, qui ont été hérités de l’objet géométrique. Parallèlement, le
rectangle possède les attributs suivants : x_coord, y_coord, isVisible, width et height.
Le thème héritage et polymorphisme sera traité plus en détail aux chapitres 3.4 et 3.4.4.
3.2.4 Caractéristiques de Java
Java est un langage de programmation orienté objet avec les caractéristiques suivantes:
• Java est basé sur les classes (voir chapitre 3.3)
• Toutes les classes Java dérivent d’une classe de base commune : Object
• Java ne soutient pas l’héritage multiple (voir chapitre 3.4)
• Java soutient le concept d’interface (Interfaces, voir chapitre 3.6)
• Java soutient le polymorphisme (voir chapitre 3.4.4)
• Les méthodes peuvent être sur écrite dans Java
3.3 Les classes et les objets
3.3.1 Définition
Considérons l’exemple des objets géométriques Circle et rectangle. Les attributs et les méthodes doivent être
définis à un endroit dans le code. Les classes permettent de réaliser cela. Les classes sont ainsi des plans de
construction ou des recettes de cuisine pour les objets et constituent ainsi la partie statique du programme. Ce qui
permet de créer des objets à partir d’une classe (instancier, voir chapitre 3.3.8), afin de produire des
exemplaires ou instances de cette classe. En comparaison avec le langage de programmation C, la classe
correspondrait à la déclaration d’une structure de donnée, et l’objet à la variable dont le type correspond à cette
structure de donnée.
L’appel de méthode est également qualifié « d’envoie d’information » à une instance.
Version 1.0, 05.03.07
Page 37
Introduction à la programmation Java
Introduction à la POO avec Java
3.3.2 La syntaxe
Une classe est définie à l’aide du mot clé class :
modifier class Classname
{
// Déclaration des attributs
// Déclaration des méthodes
}
Le nom de la classe doit être unique dans tout le projet et correspondre à celui du fichier contenant le code
source. Une classe Circle peut être définie dans un fichier « Circle.java » pour nos objets cercles.
3.3.3 Les attributs
Les attributs sont identiques aux variables des méthodes, qui ont été introduites au chapitre 2. Toutefois, leur
accessibilité ne se limite pas uniquement à une seule méthode, mais ils appartiennent à la classe en entier. Lors
de la création d’une instance d’une classe, le programme attribue de l’espace mémoire pour les attributs de cet
objet. La durée de vie des attributs est identique à celle de l’instance de la classe.
modifier class Classname
{
// Déclaration des attributs
modifier datatype name_1;
modifier datatype name_2;
...
// Déclaration des méthodes
...
}
Les attributs sont déclarés avec un modificateur (modifier en anglais : voir chapitre 3.3.5), le type de donnée et le
nom de l’attribut.
L’accès à un attribut d’une instance s’effectue avec l’opérateur point :
Instancename.Attributname
3.3.4 Les méthodes
Les méthodes statiques ont déjà été introduites dans le chapitre 2. En générale, les méthodes exécutent des
fonctions sur un objet. Ces fonctions peuvent être de nature à modification un attribut ou à exécuter une action,
comme par exemple draw() pour Circle.
En java, les méthodes ne peuvent être définies que dans les classes. Il n’est pas possible de définir des méthodes
globales.
Les méthodes sont définies de la manière suivante :
modifier class Classname
{
...
// Déclaration de la méthode
modifier returntype methodename (liste_des_paramètres)
{
// Corps de la méthode
}
...
}
La déclaration de la méthode s’effectue à l’aide du modificateur (voir chapitre 3.3.5), le type de restitution, le
nom de la méthode et la liste des paramètres pour la transmission des valeurs.
L’accès à une méthode d’une instance s’effectue avec l’opérateur point :
Instancename.Methodename()
Version 1.0, 05.03.07
Page 38
Introduction à la programmation Java
Introduction à la POO avec Java
3.3.5 Modificateur d’accès
La visibilité des classes, des méthodes et des attributs peut être définie à l’aide des mots clés public,
protected et private. Pour des raisons de complémentarité, la visibilité au niveau des paquets (packages,
voir chapitre 3.7) est également traité dans cette section.
La visibilité définit l’accessibilité des attributs ou des méthodes d’une classe (<Objet>.<Attribut>
respectivement <Object>.<Méthode>). On distique ici 4 cas : code de la même class, code d’une classe dérivée,
code du même paquet ou de code générale.
La visibilité peut être partagé en 4 niveaux
Mot clé
public
Accès possible
De partout
Pas de mot clé
De la même classe et des classes
du même paquet. Mais pas des
classes dérivés.
De la même classe, des classes
dérivées et des classes du même
paquet
protected
private
Seulement de la même classe
Description
Accessible de partout sans restriction.
N’est pas recommandé pour les attributs.
Pas d’accès en dehors du paquet.
Les attributs et les méthodes sont accessibles à partir de
la classe, contenant leurs déclarations, et à partir des
classes dérivées. Cependant cet accès n’est pas possible
à partir des instances de cette classe.
Les attributs et les méthodes privés sont masqués. Ce
qui est très restrictif car même les classes dérivées n'
y
ont pas accès. Ce type de modificateur est souvent
utilisé avec les attributs.
Figure 3 : Modificateur d’accès
Remarque concernant les mode d’accès pour les classe (class) et les interfaces (interface) : Ici il n’existe
que les accès de partout (public) ou depuis le même paquet (absence de mot clé, défaut). Pour les classes
internes (voir chapitre 3.3.11) les modificateurs private et protected sont également autorisés.
Exemple:
public class Circle
{
private int x_coord;
private int y_coord;
private int radius;
public boolean isVisible;
public void setCoord(int x, int y)
{
x_coord = x;
y_coord = y;
}
protected void draw()
{
// draws the Circle
}
private void move(int x, int y)
{
x_coord += x;
y_coord += y;
draw();
}
Version 1.0, 05.03.07
Page 39
Introduction à la programmation Java
Introduction à la POO avec Java
}
public class TestAccess
{
public static void main(String[] args)
{
Circle myCircle = new Circle ();
// myCircle.x_coord = 5;
//
myCircle.isVisible = true;
//
myCircle.setCoord(5, 7);
//
myCircle.draw();
//
// myCircle.move(1,2);
//
}
Compiler: The field myCircle.x_coord is not visible
always ok
always ok
ok for the same Package
Compiler: The method myCircle.move() is not visible
}
Description de cet exemple:
La méthode principale main(), avec laquelle le programme est démarrée, est définie dans la classe
TestAccess. Au début de cette méthode, une instance myCircle est créée à partir de la classe Circle.
Ensuite, suivent plusieurs exemples où l’on essaye d’accéder, à l’aide de l’opérateur point, aux différents
attributs et méthodes de myCircle. L’accès à l’attribut x_coord n’est pas possible, car ce dernier est déclaré
comme private dans la classe Circle. L’accès à l’attribut isVisible est par contre possible, car ce
dernier est public. La même chose est valable pour la méthode setCoord(), qui est également public.
L’appel de la méthode draw() est également possible, car les classes TestAccess et Circle sont déclarées
dans le même paquet. Si cela n’était pas le cas, draw() serait également inaccessible ici. L’appel de la méthode
move() génère également une erreur du compilateur. En effet, cette dernière est déclarée comme private
dans la classe Circle et, par conséquent, n’est accessible que dans cette classe.
3.3.6 Les diagrammes de classe
L’analyse et le design des programmes orientés objet s’effectuent le plus souvent avec des UML (Unified
Modeling Language). Les diagrammes de classe font parti des UML, les autres diagrammes sont décrits dans le
chapitre 3.8.1.
Les diagrammes de classe permettent de représenter graphiquement les différentes classes et leurs relations entre
elles.
Une classe est modélisée de la manière suivante avec les diagrammes de classe :
Nom de la classe
Attributs
Methodes
Figure 4 : Design d’une classe
L’exemple suivant montre le digramme de la classe pour la classe Circle, introduite à la section 3.3.5 :
Version 1.0, 05.03.07
Page 40
Introduction à la programmation Java
Introduction à la POO avec Java
Circle
x_coord
y_coord
radius
isVisible
setCoord()
draw()
move()
Figure 5 : Diagramme de classe de la classe Circle
Les diagrammes de classes (diagramme UML) sont générés avec des outils informatiques. Les outils
professionnel performant facilitent les phase d’analyse, de design et de codage. Ils sont capable de générer du
code à partir des diagrammes et inversement de générer un diagramme à partir de code (Reverse Engineering).
Ils indiquent également les éventuelles inconsistances aux programmeurs. Certains outils représentent également
les modificateurs à l’aide de symboles graphiques (par exemple un clé pour private).
Un programmeur professionnel définira toujours un diagramme de classe avant de coder le programme.
3.3.7 Les méthodes et les attributs de classe
Les attributs et les méthodes d’une classe sont toujours attachés à une instance « vivante ». Cela a été illustré
dans l’exemple de la section 3.3.5. Il faut d’abord instancier un objet du type Circle, afin d’en initialiser les
attributs ou d’en appeler les méthodes.
Il existe également des attributs et des méthodes, qui ne sont pas attachés une instance et qui existent depuis le
début jusqu’à la fin du programme. Ces derniers sont nommés des attributs et des méthodes de classe et sont
déclarés à l’aide du mot clé static.
Les méthodes de classe ont été souvent utilisées dans ce manuscrit, sans que cela ait été explicitement dit. La
méthode main est toujours recherchée au démarrage d’un programme. Toutefois, cette dernière doit être appelée
sans qu’aucun objet existe :
public static void main(String[] args)
main() est par conséquent une méthode de classe. Les méthodes de classe peuvent également appeler des autres
attributs et méthodes de classe, qui sont également déclarés avec le mot clé static. Le second chapitre (Aspect
fonctionnel de la programmation Java) traite uniquement des attributs et les méthodes de classe.
Exemple : La classe Circle de l’exemple de la section 3.3.5 doit être complété avec des attributs et des
méthodes de classe :
public class Circle
{
private int x_coord;
private int y_coord;
private int radius;
public boolean isVisible;
public static int myClassAttr = 8;
public void setCoord (int x, int y)
{
x_coord = x;
y_coord = y;
myClassAttr++;
}
Version 1.0, 05.03.07
// Attribute of the class
// Access possible to the class attribute
Page 41
Introduction à la programmation Java
Introduction à la POO avec Java
public static void printInfo()
{
//isVisible = false;
// Method of the class
// Error, the access to the class attribute
// is not possible from the class method!
System.out.println("myClassAttr = " + myClassAttr);
// is ok.
}
}
public class ClassMethod
{
public static void main(String[] args)
{
// Test the access to the class method of Circle,
// no object Circle has been instantiated !
Circle.printInfo();
// Ok
//myClassAttr = 6;
// Error
Circle.myClassAttr = 5;
// Ok
//Circle.isVisible = true;
// Error, it is not a class attribute
Circle.printInfo();
// Ok
//Circle.setCoord(5,7);
// Error, it is not a class attribute
// Test the access to the object method
Circle myCircle = new Circle();
meinCircle.isVisible = true;
// Ok
meinCircle.myClassAttr = 6;
// Ok
meinCircle.printInfo();
// Ok
meinCircle.setCoord(5,7);
// Ok
}
}
Affichage sur l’écran:
myClassAttr = 8
myClassAttr = 5
myClassAttr = 6
Remarque: Les méthodes et les attributs de classe sont accessibles à l’aide du nom de la classe et de l’opérateur
point. Il est également possible de les accéder à l’aide du nom de l’instance. Toutefois, cela est moins courant.
3.3.8 Instancier un objet, constructeur
La création d’un objet concret à partir d’une classe et qualifié d’instancier. Pour cela on utilise l’opérateur new.
Une instance de la classe Circle a été créée dans l’exemple du chapitre 3.3.5 :
Circle myCircle = new Circle();
La formulation générale est la suivante :
<Classtyp> <Instance_Name>;
<Instance_Name> = new <Classtyp ()>;
Ou :
<Classtyp> <Instance_Name> = new <Classtyp()>;
Instance_Name est une référence, qui adresse l’instance créée à partir de la classe Classtyp. Les attributs
et les méthodes de cette instance peuvent être accédées à l’aide de cette référence. new créé un nouveau objet, et
attribue son adresse à la référence Instance_Name. Le collecteur d’ordure (Garbage Collection) élimine
cette instance, lorsqu’il n’est plus utile.
Version 1.0, 05.03.07
Page 42
Introduction à la programmation Java
Introduction à la POO avec Java
Durant la création d’instance, la quantité de mémoire nécessaire pour le nouvel objet est déterminée par la
machine virtuelle. Cette quantité dépend des attributs, qui ont été définies dans la classe. Par conséquent, la
même quantité de mémoire sera allouée pour des objets de même classe.
Les constructeurs sont des méthodes spéciales, qui sont appelées durant la création d’instance avec new, afin
d’initialiser l’objet. Les constructeurs ont les caractéristiques suivantes :
• Ils ont le même nom que la classe
• Ils ne possèdent pas de type de retour et pas de modificateur
• Ils continent une liste de paramètre, pour la transmission des arguments
• Ils peuvent être sur écrites
Exemple: La classe Cirlce avec deux constructeurs et la méthode main():
public class Circle
{
private int x_coord;
private int y_coord;
private int radius;
private boolean isVisible;
// 1. constructor, without parameter
Circle()
{
System.out.println("1. constructor without parameter");
x_coord = 1;
y_coord = 1;
radius = 1;
isVisible = false;
}
// 2. constructor, with parameter
Circle(int x, int y, int r, boolean isVisible)
{
System.out.println("2. constructor with parameter");
x_coord = x;
y_coord = y;
radius = r;
this.isVisible = isVisible;
}
// Printing all the arguments on the screen
public void printCircle()
{
System.out.println("x_coord = " + x_coord);
System.out.println("y_coord = " + y_coord);
System.out.println("radius = " + radius);
System.out.println("isVisible = " + isVisible);
System.out.println("");
}
// Beginning of the main program
public static void main(String[] args)
{
System.out.println("Start Program");
Circle Circle1 = new Circle();
Circle1.printCircle();
// Instance of 1. Circle
Circle Circle2 = new Circle(3,7,10,true); // Instance of 2. Circle
Circle2.printCircle();
}
}
Version 1.0, 05.03.07
Page 43
Introduction à la programmation Java
Introduction à la POO avec Java
Affichage sur l’écran:
Start Programm
1. constructor withou parameter
x_coord = 1
y_coord = 1
radius = 1
isVisilbe = false
2. constructor with parameter
x_coord = 3
y_coord = 7
radius = 10
isVisilbe = true
Un instance de Circle est créé au départ dans main(). Ici, le premier constructeur de Circle est appelé, car
aucun argument n’est transmis à l’opérateur new. Ensuite, la méthode printCircle() de l’instance
Circle1 est appelé, afin d’afficher les valeurs défaut des attributs. Une deuxième instance Circle2 est créée.
Dans ce second cas, des arguments sont transmis à l’opérateur new. Le deuxième constructeur est ainsi appelé,
afin d’initialiser les attributs.
Le nom du 4ème paramètre du 2ème constructeur (isVisible) est identique à celui d’un des attributs. Cela est
très utile pour ne pas devoir toujours rechercher des nouveaux noms pour les paramètres. Toutefois, dans ce cas
il faut utiliser le mot clé this pour l’opération d’attribution :
this.isVisible = isVisible;
this est une référence sur l’objet courant. Ainsi il est possible de définir en Java des noms de paramètres
identiques à ceux des attributs.
Important:
• Lorsqu’une classe ne possède pas de constructeur, le système crée automatiquement un constructeur défaut
sans paramètre.
• Lorsqu’une classe possède au mois un constructeur, le système ne crée pas de constructeur défaut sans
paramètre. Ainsi, si un tel constructeur est nécessaire, il faut le programmer (voir exemple de ci-dessus)
Remarque: Un programme OO n’est finalement qu’une collection d’instances, qui ont les propriétés suivantes :
• Elles sont créés à un instant donné et sont de nouveau détruites lorsqu’elles ne sont plus utiles.
• Elles communiquent entre elles par appel de méthode.
3.3.9 Destructeur et collecteur d’ordure (Garbage Collection)
Une instance a besoin d’espace mémoire pour ses attributs. La fin de vie de cette instance est reconnue par le
collecteur d’ordure, qui la détruit pour libérer à nouveau de l’espace mémoire. Ce mécanisme empêche la
saturation de l’espace mémoire et permet ainsi de continuer d’instancier des nouveaux objets. Le collecteur
d’ordure détruit une instance, lorsque cette dernière n’est plus adressée par une référence. Le programmeur est
responsable de cela.
Dans certain cas il faut réaliser également des travaux de rangement durant la destruction des instances. Cela est
notamment le cas lorsque des instances occupent des ressources (appareils, fichiers, sockets etc.). La première
solution pour ce problème est la programmation d’une méthode close(), pour libérer ces ressources Toutefois,
l’appel de cette méthode est sous la responsabilité de l’utilisateur ! Une solution plus élégante est l’utilisation de
destructeurs. En analogie avec les constructeurs, les destructeurs sont appelés avant la destruction de
l’instance par le collecteur d’ordure.
Dans java le destructeur est une méthode, qui s’appelle finalize() et qui possède les propriétés suivantes :
Version 1.0, 05.03.07
Page 44
Introduction à la programmation Java
Introduction à la POO avec Java
•
Elle s’appelle finalize()
•
•
•
Elle possède le type de restitution void
Elle n’a pas de paramètres
finalize(), contrairement au constructeur, peut être appelée par des méthodes standards. finalize()
devrait être protégée des appels multiples.
Exemple :
public class Test
{
private int count;
Test(int count)
// Constructor
{
this.count = count;
System.out.println("Constructor " + count + ". Object");
}
protected void finalize()
// Destructor
{
System.out.println("Destructor " + count + ". Object");
}
}
public class TestDestructor
{
public static void print(int i)
{
Test localTest = new Test(i);
}
public static void main(String[] args)
{
System.out.println("Start of Program");
Test myTest;
myTest = new Test(1);
print(2);
System.gc();
System.out.println("Middle of Program");
myTest = null;
System.gc();
System.out.println("End of Program");
}
// Creation of the 1. object
// Destruction of the 1. object
// Creation of the 1. object
// Creation of the 2. object
// Calling garbage collection
// Release the 1. object
// Calling garbage collection
}
Affichage sur l’écran:
Start Programm
Constructor 1. Object
Constructor 2. Object
Destructor 2. Object
Middle of Programm
Destructor 1. Objekt
End of Programm
Au début de main(), un objet local myTest est crée à partir de la class Test. L’appel de la méthode print()
génère une deuxième instance de Test, qui sera de nouveau libérée, car elle n’apparaît que dans print(). Le
premier objet sera libéré à son tour avec l’annulation de sa référence (myTest = null). Le collecteur
d’ordure (Garbage Collection) est appelé normalement en arrière plan à des moments quelconques par le
système. Toutefois pour mieux illustrer la destruction des objets dans cet exemple, le destructeur d’ordure a été
appelé explicitement avec l’instruction « System.gc ». Normalement, cela ne devrait pas être nécessaire.
Version 1.0, 05.03.07
Page 45
Introduction à la programmation Java
Introduction à la POO avec Java
Important :
Même si cela a déjà été mentionné dans ce cours : Lorsque vous passez de Java à C++, vous devez vous
habituer à libérer explicitement la mémoire allouée aux objets (souvent dans le destructeur). Dans C++
chaque classe devrait ainsi contenir un destructeur, afin de pouvoir libérer toutes les ressources mises à
disposition pour elle. Alors que dans Java, cette libération ne devrait se limite qu’aux ressources autres
que la mémoire.
3.3.10 Transmission et retour des objets
Les objets peuvent également être transmis comme paramètre aux méthodes ou retournés par ces dernières.
Comme chaque objet est toujours adressé par une référence, il suffit de transmettre la référence.
public class Fraction
{
// Attribute
int numerator;
int denumerator;
// Constructor
Fraction(int numerator, int denumerator)
{
if(denumerator != 0)
{
this.numerator = numerator;
this.denumerator = denumerator;
}
else
{
System.out.println("Division with null");
this.numerator = 0;
this.denumerator = 1;
}
}
// Multiplication
public Fraction mul(Fraction para)
{
Fraction res = new Fraction(0, 1);
res.numerator = numerator * para.numerator;
res.denumerator = denumerator * para.denumerator;
return(res);
}
// is denumerator different from null
// new instance for result
// multiplication with numerator
// multiplication with denumerator
public void print()
{
System.out.println(numerator + "/" + denumerator);
}
public static void main(String[] args)
{
int z1, n1;
int z2, n2;
if(args.length == 4)
{
z1 = Integer.parseInt(args[0]);
n1 = Integer.parseInt(args[1]);
z2 = Integer.parseInt(args[2]);
n2 = Integer.parseInt(args[3]);
Fraction b1 = new Fraction(z1, n1);
b1.print();
Fraction b2 = new Fraction(z2, n2);
b2.print();
Version 1.0, 05.03.07
// reading the parameter
// create Fraction 1 and 2
Page 46
Introduction à la programmation Java
Introduction à la POO avec Java
Fraction b3 = b1.mul(b2);
b3.print();
// multiplication
}
else
{
System.out.println("Please enter 4 parameters:");
System.out.println("Numerator1, Denumerator1, Numerator2, Denumerator2");
}
}
}
Appel de la fonction avec les paramètres suivants :
"3"
"5"
"7"
"8"
Affichage sur l’écran :
3/5
7/8
21/40
L’intérêt principale de cet exemple est la méthode mul(), qui reçoit un objet Fraction comme argument. La
multiplication y est réalisée entre ces arguments et les valeurs internes de l’objet. Au début de cette méthode un
objet de la classe Fraction est créé pour le stockage du résultat. Ce dernier sera retourné comme référence à la fin
de la méthode.
La méthode mul() est appelé dans le programme principal avec l’instruction suivante :
Fraction b3 = b1.mul(b2);
// Multiplication
Une multiplication entre les instances b1 et b2 est alors réalisé et le résultat est stocké dans b3. Remarquez que
l’objet b3 est créé dans la méthode mul().
3.3.11 Les classes internes
Dans Java les classes peuvent également être définies à l’intérieur d’autres classes. Ces classes sont appelées
« classes internes » et possèdent les propriétés suivantes :
• Elles peuvent accéder aux attributs et aux méthodes de la classe externe (même les éléments privés).
• Des instances de la classe interne peuvent être créées dans la classe externe. Les éléments de ces instances
sont accessibles par la classe externe.
• Les classes internes ne sont visible en dehors du bloque, qui contient leur définition, qu’avec un nom
qualifié. Ce dernier est « ClasseExtren.ClasseInterne ».
Exemple:
public class ExternClass
{
private int ExternVariable = 10;
// Intern class
public class InternClass
{
public int InternVariable = 10;
public void test(int i)
{
InternVariable = ExternVariable * 2;
System.out.println("test() InternClass " + i);
}
}
public void test(int i)
{
System.out.println("test() ExternClass " + i);
Version 1.0, 05.03.07
Page 47
Introduction à la programmation Java
Introduction à la POO avec Java
InternClass internClass = new InternClass();
internClass.test(i);
}
}
public class TestInternClass
{
public static void main(String[] args)
{
// Call the extern class
ExternClass extern = new ExternClass();
extern.test(1);
// Call the intern class
ExternClass.InternClass intern = extern.new InternClass();
intern.test(2);
}
}
Affichage sur l’écran:
test() ExternClass 1
test() InternClass 1
test() InternClass 2
Au début du programme principale, une instance de la classe ExternClass est créée et la méthode test()
en est appelée. Dans cette méthode, une instance de la classe interne est à nouveau créée et la méthode test de
cette instance est également appelée. Ensuite, une instance de la classe interne est directement créée dans
main(). Remarquez le nom qualifié da la classe et l’opérateur new.
Normalement il n’y a pas d’accès depuis l’extérieur de la classe externe sur la classe interne.
3.4 Héritage
3.4.1 Fondement
La programmation OO sans héritages serait comme des pâtes italienne sans verres de vin rouge. Le but de
l’héritage est de rassembler le codes identique des différents classes dans une super classe (que l’on nomme
également classe parent). La super classe peut transmettre ainsi ses propriétés (attributs et méthodes) aux sous
classes. Des nouvelles propriétés peuvent être ajoutées dans les sous classes. Une sous classe peut également sur
écrire une méthode héritée de la super classe. C. à d. qu’elle peut redéfinir cette méthode. L’héritage est
également qualifié de dérivation ou de spécialisation.
Le principe d’héritage apporte les avantages suivants :
• L’héritage permet de réduire la redondance du code. Le code en commun est défini dans une super classe.
L’effort de programmation peut ainsi être réduit.
• Le code ajouté dans une super classe (comme par ex. une nouvelle méthode) est également disponible dans
les basses classes.
• Les changements de code dans les hautes classes sont également valables pour les basses classes. Ce qui
permet de réduire de manière significative l’effort de test.
• Des nouvelles basses classes peuvent toujours être ajoutées dans une bonne hiérarchie de classes. Le
programme peut être ainsi étendu, sans changement du code existant.
• La hiérarchie des classes correspond au monde réel (objets graphiques, personnes, véhicules, le monde
animal, le monde végétal etc.). le programme devient ainsi plus accessible et plus compréhensible.
• Le code est ainsi réutilisable pour d’autres applications. Il est possible d’utiliser des classes existantes et les
modifier à l’aide du principe d’héritage.
Version 1.0, 05.03.07
Page 48
Introduction à la programmation Java
Introduction à la POO avec Java
Propriétés de l’héritage dans Java :
• Dans Java une sous classe ne peut hériter que d’une seule super classe. Par conséquent, « l’héritage
multiple » n’est pas possible.
• Lorsqu’une classe ne possède pas de super classe, elle héritera automatiquement de la classe Object.
Toutes les classes possèdent ainsi les propriétés de la classe Object, car les classes supérieures héritent les
propriétés d’Object et les transmettent aux classes inférieures.
• Dans la sous-classe le mot clé extends sert à faire connaître la super classe, à partir de laquelle l’héritage
doit avoir lieu.
• Les constructeurs des super classes sont appelés avec le mot clé super. super est également utilisé pour
désigner dans une méthode de la sous-classe une méthode de la super classe ayant le même nom (méthode
sur écrite).
Important:
Le design d’une hiérarchie des classes, c. à d. la recherche du code en commun des différentes classes, est
une tâche très exigeante et intéressante. Un bon diagramme de classe dans un projet complexe nécessite
beaucoup de temps et d’expérience. Le résultat est en général une structure stable et un entretient facilité
du programme.
L’héritage est illustré de la manière suivante dans les diagrammes de classe :
Classe
parent
Classe
enfant
Figure 6 : Héritage avec les diagrammes de classe
Exemple pour une super classe Parent et une sous classe Child: La super classe doit contenir les 3 attributs
p1, p2 et p3. Ces derniers ont respectivement les modificateurs public, protected et private. En plus
elle contient un constructeur ainsi que les méthodes do() et print(). La classe Child hérite tous ces
propriétés et possède en plus un attribut c1, un constructeur Child() ainsi que les méthode doChild() et
print(). La méthode print() de la classe Child sur écrit la méthode print() de la super classe. Le
diagramme de classe est ici le suivant :
Parent
int p1
int p2
int p3
Parent()
doParent()
print()
Child
int c1
Child()
doChild()
print()
Figure 7 : Diagramme de classe pour l’exemple Parent et Child
Version 1.0, 05.03.07
Page 49
Introduction à la programmation Java
Introduction à la POO avec Java
public class Parent
{
// Attribut
public int p1;
protected int p2;
private int p3;
// Constructor
Parent(int p1, int p2, int p3)
{
System.out.println("Constructor of class Parent");
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
}
protected void doParent()
{
System.out.println("doParent() of class Parent");
}
public void print()
{
System.out.println("print() of class Parent");
System.out.println("p1: " + p1 + " p2: " + p2 + "
}
p3: " + p3);
}
public class Child extends Parent
{
// Attribut
protected int c1;
// Constructor
Child(int c1, int p1, int p2, int p3)
{
super(p1, p2, p3);
// Call constructor of Parent
System.out.println("Constructor of class Child");
this.c1 = c1;
}
protected void doChild()
{
System.out.println("doChild() of class Child");
doParent();
// Methode doParent() of Parent
}
public void print()
// Redefine print of Parent
{
System.out.println("print() of class Child");
super.print();
// Call print() of Parent
System.out.println("c1: " + c1);
}
public static void main(String[] args)
{
Child child = new Child(1, 2, 3, 4);
child.doChild();
child.print();
child.p1 = 0;
child.p2 = 0;
//child.p3 = 0;
}
// Create a instance of Child
// ist ok because p1 is public
// ist ok because p2 is protected
// error because p3 is private
}
Version 1.0, 05.03.07
Page 50
Introduction à la programmation Java
Introduction à la POO avec Java
Affichage sur l’écran :
Constructor of class Parent
Constructor of class Child
doChild() of classe Child
doParent() of class Parent
print() of class Child
print() or class Parent
p1: 2 p2: 3 p3: 4
c1: 1
Un instance de la classe Child est créée au début du programme principale main(). Le constructeur de la
classe Child est ainsi appelé par le système. Tout au début de cette méthode, le constructeur de la super classe
Parent est appelé. Cela est important, car il faut d’abord initialiser la super classe Parent, avant que la sous
classe Child puisse hériter les propriétés de Parent. En général un constructeur doit toujours appeler au début
le constructeur de la super classe, lorsque cette dernière est disponible, et ensuite exécuter ses propres
instructions. La seconde instruction de main() est l’appel de la méthode doChild(). Cette dernière appel à
son tour la méthode doParent() de la super classe. Ce qui est correct, car Child ne contient pas de méthode
du même nom. Dans Java, il est possible d’appeler dans une sous-classe toutes les attributs et les méthodes de la
super classe, pourvu que les appels soient uniques. La méthode print() de Child sur écrit la méthode
print() de Parent. C. à d. qu’ici la méthode print() de la super classe n’est pas complète pour la sous
classe et doit par conséquent être adaptée ou sur écrite. Souvent le code de la méthode de la super classe peut
être utilisé dans la sous-classe, moyennant quelques adaptations, comme cela est le cas dans cet exemple avec
l’affichage de c1. Ainsi la méthode print() de la super classe est appelée depuis la méthode print() de la
sous classe. Toutefois cet appel n’est pas unique (cela voudrait dire que l’on appel la méthode print() de
Child), par conséquent, cette dernière est appelé avec super.print(). Ainsi la méthode print() de la
super classe affiche au début les attributs de cette dernière, suivi de l’affichage de l’attribut c1 par la méthode
print() de la sous classe.
L’accès à l’attribut child.p1 est correct dans main(), car p1 a été déclaré comme public. L’accès à
child.p2 est également correct, car p2 a été décelé comme protected. Toutefois l’accès à child.p3
n’est pas possible, car p3 a été déclaré comme private. L’accès à p3 n’est que possible dans la super classe.
3.4.2 Ordre des constructeurs et des destructeurs
L’ordre de l’appel des constructeurs et des destructeurs est régit par les règles suivantes :
1) La première instruction dans un constructeur doit être l’appel du constructeur de la super classe avec le mot
clé super. Si cela n’est pas définit explicitement, c’est le constructeur par défaut qui va être appelé. Ce
dernier doit par conséquent exister inévitablement, si non le compilateur génère un message d’erreur.
2) La conséquence du point ci dessus est qu’un seul constructeur de la super classe ne peut être appelé.
Le constructeur de la super classe est ainsi toujours appelé en premier suivi du constructeur de la sous-classe.
Cet ordre est inversé avec les destructeurs. Ici le destructeur de la sous-classe est exécuté en premier, suivi du
destructeur de la super classe. Toutefois, le méthode finalize() de la super classe doit être appelée
explicitement.
Exemple:
public class Parent
{
// Attribut
public int p1;
protected int p2;
private int p3;
// Constructor
Parent(int p1, int p2, int p3)
{
System.out.println("Constructor class Parent");
Version 1.0, 05.03.07
Page 51
Introduction à la programmation Java
Introduction à la POO avec Java
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
}
// Destructor
protected void finalize()
{
System.out.println("Destructor class Parent");
}
public void print()
{
System.out.println("print() class Parent");
}
}
public class Child extends Parent
{
// Attribut
protected int c1;
// Constructor
Child(int c1, int p1, int p2, int p3)
{
super(p1, p2, p3);
// Call the constructor of class Parent
System.out.println("Constructor classe Child");
this.c1 = c1;
}
// Destructor
protected void finalize()
{
System.out.println("Destructor classe Child");
super.finalize();
// Call destructor of class Parent
}
public void print()
// Redefine the methode print of Parent
{
System.out.println("print() class Child");
super.print();
// call print() of class Parent
}
}
public class TestOrder
{
public static void main(String[] args)
{
Child child = new Child(1, 2, 3, 4);
child.print();
child = null;
System.gc();
}
}
// Instanciate Child
// Release object child
// Call Carbage Collection
Affichage sur l’écran:
Constructor class Parent
Constructor class Child
print() class Child
print() class Parent
Destructor class Child
Destructor class Parent
Version 1.0, 05.03.07
Page 52
Introduction à la programmation Java
Introduction à la POO avec Java
Une instance de la classe Child est créée dans le programme principal. Le code du constructeur de la super
classe est ainsi exécuté en premier, suivi de celui du constructeur de la sous-classe. L’instance child est libéré
avec l’instruction « child = null » et éliminé à l’aide du collecteur d’ordure. Le code du destructeur de la
sous-classe est ainsi exécuté en premier suivi du celui du destructeur de la super classe.
3.4.3 Les classes et méthodes abstraites
Dans certain cas, des objets abstraits peuvent être obtenus de l’assemblage des propriétés communes de
différentes classes dans une super classe. Ces supers classes sont alors qualifiées d’abstraites. Il n’existe ainsi pas
d’objets géométriques concrets, mais seulement des cercles, des rectangles etc. Une méthode abstraite est une
méthode, qui est déclarée uniquement avec sa signature, et doit par conséquent être implémentée dans la sousclasse.
Propriétés des classes abstraites:
• Chaque classe abstraite doit contenir au moins une méthode abstraite.
• Il n’est possible de créer des instances à partir des classes abstraites.
• Les méthodes abstraites doivent être implémentées dans les sous classes.
• Un objet de la sous-classe ne peut être instancié que si cette dernière implémente toutes les méthodes
abstraites, héritées de la super classe. Ci cela n’est pas le cas, la sous classe est également une classe
abstraite.
En Java les classes et les méthodes abstraites sont définies à l’aide du mot clé abstract :
public abstract class SuperClass
{
public abstract void method();
}
// Abstract method
public class SubClass extends SuperClass
{
public void method()
// Implementation in the SubClass
{
// Implementation
}
}
L’exemple des objets géométriques peut être complété à présent avec l’introduction d’une classe
abstraite « GeometricalObject ». Cette classe doit contenir une méthode area() pour le calcul de la
surface. Cette méthode est également abstraite, car il n’est pas possible de calculer la surface d’un objet
géométrique sans en connaître la forme. La méthode area() doit ainsi être implémentée dans la sous-classe. La
déclaration de la méthode area() fournit ici une interface commune pour toutes les objets géométriques. Ce
sujet est traité plus en au chapitre 3.4.4.
Exemple:
Version 1.0, 05.03.07
Page 53
Introduction à la POO avec Java
Introduction à la programmation Java
abstract
GeometricalObject
x_coord
y_coord
isVisible
GeometricalObject()
setCoord()
draw()
move()
area()
Circle
Rectangle
radius
width
height
Circle()
area()
getRadius()
Rectangle()
area()
getWidth()
getHeight()
Figure 8 : Diagramme de classe des objets géométriques
public abstract class GeometricalObject
{
// Attribut
protected double x_coord;
protected double y_coord;
protected boolean isVisible;
// Constructor
GeometricalObject(double x, double y, boolean isVisible)
{
x_coord = x;
y_coord = y;
this.isVisible = isVisible;
}
public void setCoord(double x, double y)
{
x_coord = x;
y_coord = y;
}
public void draw()
{
// do something
}
public void move(double x, double y)
{
x_coord += x;
y_coord += y;
}
public abstract double area();
// Abstract methode
}
Version 1.0, 05.03.07
Page 54
Introduction à la programmation Java
Introduction à la POO avec Java
public class Circle extends GeometricalObject
{
// Attribut
protected double radius;
protected static final double PI = 3.1415;
// Consructor
Circle(int x, int y, int r, boolean isVisible)
{
super(x, y, isVisible);
radius = r;
}
public double area() {return(radius * radius * PI);} // Implementation of area()
public double getRadius() {return(radius);}
}
public class Rectangle extends GeometricalObject
{
// Attribut
protected double width;
protected double height;
// Constructor
Rectangle (double x, double y, double width, double height, boolean isVisible)
{
super(x, y, isVisible);
this.width = width;
this.height = height;
}
public double area() {return(width * height);}
public double getWidth() {return(width);}
public double getHeight() {return(height);}
// Implementation of area()
}
public class TestAbstract
{
public static void main(String[] args)
{
// Instanciate the objects
Rectangle rectangle = new Rectangle (1,3,10,5,true);
Circle Circle = new Circle(3,7,5,true);
// Display the area
System.out.println("Rectangle area: " + rectangle.area());
System.out.println("Circle area: "
+ Circle.area());
}
}
Affichage sur l’écran:
Rectangle area: 50.0
Circle area: 78.53750000000001
Dans l’exemple ci-dessus, la classe GeometricalObject et sa méthode area sont abstraites. Les classes
Circle et Rectangle dérivent de cette super classe et implémentent par conséquent la méthodes area(),
en fonction du calcul de leur surface. Pour chaque classe une instance est créée dans la méthode principale
main() afin de tester l’appel de la méthode area().
Version 1.0, 05.03.07
Page 55
Introduction à la programmation Java
Introduction à la POO avec Java
3.4.4 Polymorphisme
Le chapitre précédent illustre l’implémentation d’une méthode abstraite de la super classe dans une sous-classe.
Mais il est également possible de sur écrire les méthodes héritées de la super classe dans une sous-classe. Cela
est également connu sous le nom de Overriding. Chaque classe peut ainsi adapter spécifiquement une méthode
pour son propre besoin, même si cette dernière a déjà été implémentée dans la super classe.
Durant l’exécution du code, le mécanisme du polymorphisme appellera la méthode adéquate en fonction du
type de l’objet. Le polymorphisme (appelé également association dynamique ou « late binding ») apporte les
avantages suivants :
• Le choix de la bonne méthode en fonction du type de l’objet se fait automatiquement durant exécution du
programme. Les distinctions de type de donnée dans le code pour effectuer le choix de la bonne méthode ne
sont ainsi pas nécessaires.
• Les modifications de code sont beaucoup plus simples. Car il est possible d’hériter à partir des classes
existantes et d’en modifier spécifiquement certaines méthodes par des opération de sur écriture.
Toutefois le polymorphisme possède également des désavantagés :
• exécution du programme nécessite plus de ressources. Le code devient notamment plus lent, car la bonne
méthode doit être déterminée durant l’exécution du programme.
• Le débuggage des méthodes appelées devient plus difficile.
Dans l’exemple du chapitre 3.4.4, deux instances du type Circle et Rectangle ont été créées dans la
méthode principale main(). Ensuite, la méthode area() a été appelé pour ces deux objets. Ce code n’est pas
encore très élégant. A l’aide du polymorphisme les deux instances Circle et Rectangle peuvent être créées
dans un container pour objets géométriques. La méthode area() pourra ainsi être appelée à partir de ces objets
géométriques. Le choix de la bonne méthode s’effectuera automatiquement durant exécution du programme. C. à
d. que pour l’objet Circle ce sera la méthode de la classe Circle et pour l’objet Rectangle la méthode de
l’objet Rectangle .
Exemple:
public class TestPolymorphism
{
public static void main(String[] args)
{
GeometricalObject geo [];
geo = new GeometricalObject[2];
geo[0] = new Rectangle (1,3,10,5,true);
geo[1] = new Circle(3,7,5,true);
for (int i = 0; i < geo.length; i++)
System.out.println("Surface: " + geo[i].area());
}
}
Affichage sur l’écran:
Surface : 50.0
Surface: 78.53750000000001
Un tableau pour deux objets géométriques est défini au début de l’exemple de ci dessus. Ensuite des instances de
Rectangle et Circle sont créé et déposé dans ce tableau. La méthode area() est appelée pour chaque
objet à l’aide d’un boucle à la fin de cet exemple. La bonne méthode sera défini automatiquement durant
exécution du programme, c. à d. d’abord la méthode pour l’objet Rectangle et ensuite celle pour l’objet
Circle. Ce code est très facile à entretenir : Des nouvelles classes peuvent être définies pour les objets
géométriques (ex. Triangle) et leurs instances peuvent être déposées de la même manière dans le tableau.
Version 1.0, 05.03.07
Page 56
Introduction à la programmation Java
Introduction à la POO avec Java
3.4.5 Les casting des classes
Admettons que les classes Circle et Rectangle possèdent beaucoup de méthode en commun et qu’a coté
elles possèdent des méthodes plus spécifiques, qui n’apparaissent que dans les sous-classes. Par exemple la
classe Rectangle pourrait avoir une méthode rotate(), qui ne serait pas définie dans la classe Circle.
Si les instances des objets étaient stockées dans un tableau, comme dans l’exemple du chapitre 3.4.4, le code
suivant pour un rectangle serait faux et générerait une erreur de compilation :
geo[0].rotate();
Ce code est faux, car la méthode rotate() n’est pas définie pour les objets géométriques. Il faut donc
transformer l’objet géométrique en rectangle, afin de pouvoir en appeler la méthode rotate(). Cela est réalisé
avec un opérateur cast de la manière suivante :
((Rectangle )geo[0]).rotate();
Ce code est dangereux car il peut être exécuté avec des objets du type Circle, qui ne possèdent pas la méthode
rotate(). Ce qui va générer des exceptions du type ClassCastException durant l’exécution du
programme.
Il est donc nécessaire de vérifier le type de l’instance avant d’appeler la méthode rotate(). Cela peur être
réalisé de la manière suivante :
if(geo[0] instanceof Rectangle )
((Rectangle )geo[0]).rotate();
Exemple : Le code de l’exemple 3.4.4 doit être complété de la manière suivante :
• La classe rectangle ait une méthode rotate()
• Le programme fournisse également la forme de l’objet géométrique durant la phase de calcul de la surface
public class Rectangle extends GeometricalObject
{
// Attribute
protected double width;
protected double height;
// Constructor
Rectangle (double x, double y, double width, double height, boolean isVisible)
{
super(x, y, isVisible);
this.width = width;
this.height = height;
}
public
public
public
public
double area() {return(width * height);}
double getWidth() {return(width);}
double getHeight() {return(height);}
void rotate(int angle) {System.out.println("rotate");}
}
public class TestClassCast
{
public static void main(String[] args)
{
GeometricalObject geo [];
geo = new GeometricalObject[2];
geo[0] = new Rectangle (1,3,10,5,true);
geo[1] = new Circle(3,7,5,true);
//geo[0].rotate();
((Rectangle )geo[0]).rotate(30);
Version 1.0, 05.03.07
// method rotate() is
// is ok
undefined
Page 57
Introduction à la programmation Java
Introduction à la POO avec Java
//((Rectangle )geo[1]).rotate(30); // ClassCastException
for (int i = 0; i < geo.length; i++)
{
if(geo[i] instanceof Rectangle )
System.out.println("Surface Rectangle : " + geo[i].area());
else if(geo[i] instanceof Circle)
System.out.println("Surface Circle: " + geo[i].area());
}
}
}
Affichage sur l’écran:
rotate
Surface Rectangle : 50.0
Surface Circle: 78.53750000000001
Au début du programme principal des essais de rotation ont lieu. Cela entraîne une erreur de compilation, car les
objets géométriques ne possèdent pas de méthode rotate(). Il s’en suit une opération de cast sur le premier
objet géométrique, qui modifie le type de ce dernier en Rectangle . Ce qui est correct, car le premier objet
géométrique dans le tableau est un rectangle, et la méthode rotate() peut être appelé pour cet objet. Une
seconde opération de cast est également exécutée sur le deuxième objet géométrique, qui est un Circle, pour
en faire un Rectangle . Ce qui permet également d’appeler la méthode rotate()pour cet objet. Au niveau
de la syntaxe cette instruction est absolument correcte. Toutefois, durant l’exécution du programme une
exception du type ClassCastException sera lancée ici. Dans la boucle for, un control a lieu afin de
déterminer le type de l’objet géométrique. Ce qui est la meilleure variante pour appeler les méthodes spécifiques
aux classes.
Remarque:
Le casting n’est fondamentalement pas une forme élégante de codage. Toutefois, ce dernier ne peut pas
toujours être évité. Dans ce cas, il faudrait d’abord réévaluer toutes les variantes du design avant
d’utiliser un opérateur cast.
Le casting peut être évité dans le code ci-dessus. Dans un premier temps il faudrait définir dans la classe
GeometricalObject la méthode non abstraite rotate(), qui n’aurait aucune tâche. Cette méthode devrait
alors être sur écrite dans la classe Rectangle. Dans un deuxième temps, le texte pour l’affichage de la surface
devrait être transféré dans les sous classes.
3.5 Relation entre les classes
Les classes peuvent avoir des relations différentes entre elles. Ces relations sont représenté dans les diagrammes
de classe. Les relations les plus importantes sont les suivantes :
Relation
Héritage
"est un"
Description
Diagramme de classe en UML
Cette relation découle de l’héritage. On dit: B est un A,
A
lorsque B dérive de A.
Exemple: Un Circle est un objet géométrique.
B
Aggregation
"contient"
Un objet de la classe B fait partie d’un objet de la classe
A, mais son existence ne dépend pas de celle de l’objet
de la classe A.
A
B
Exemple : Un étudiant possède une machine à calculer.
Version 1.0, 05.03.07
Page 58
Introduction à la POO avec Java
Introduction à la programmation Java
Composition
"possède"
Association
"utilise"
Un objet de la classe B fait partie d’un objet de la classe
A et son existence dépend de celle de l’objet de la
classe A.
Exemple: Un arbre possède un tronc et des racines.
Une association est une relation structurelle entre deux
classes.
A
B
A
B
Exemple : La classe GraphicalObject peut utiliser
la méthode print() de la classe Printer, pour
afficher les objets géométriques.
Figure 9 : Relation entre différentes classes
Remarque: Les relations entre les classes peuvent induire en erreur ! Un cercle n’est pas un point avec des
propriétés supplémentaire, mais contient un point comme centre.
Exemple: Une classe A doit posséder un attribut de la classe C. La classe C utilise la classe D pour s’afficher.
Une classe B hérite les propriétés de la classe A.
A
C
D
Method_A()
Method_C()
Method_D()
C c
B
Method_B()
Figure 10 : Diagramme de classe illustrant les relations entre les classes
public class D
{
public static void Method_D(String str)
{
System.out.println(str);
}
}
public class C
{
public void Method_C()
{
D.Method_D("Hallo");
}
}
public class A
{
C c;
A() { c = new C();}
// Composition
// Constructor
protected void Method_A()
{
c.Method_C();
}
}
Version 1.0, 05.03.07
Page 59
Introduction à la POO avec Java
Introduction à la programmation Java
public class B extends A
{
public static void main(String[] args)
{
B b = new B();
b.Method_A();
}
}
// Method of the super class
Un objet de la classe B est instancié dans la méthode principale main(). La méthode Method_A() de la super
classe y est ensuite appelée. Cela est possible car la classe B est une classe A et que, par conséquent, il hérite les
méthodes de la super classe. La classe A possède un attribut de la classe C (composition), qui sera instancié dans
son constructeur. L’existence de l’instance c dans A est ainsi identique à celle de l’objet b du programme
principal. La méthode Method_C() de c est appelé dans la méthode Method_A(). Cette dernière appelle à
son tour la méthode Method_D(), qui a été déclarée comme static dans la classe D. D est indépendant de C.
3.6 Les interfaces
Le principe d’héritage a été introduit au chapitre 3.4. Toutefois, l’héritage multiple n’est pas soutenu en Java et,
par conséquent, une classe ne peut étendre qu’une seule super classe. Exemple : Un programme contient une
classe GeometricalObject et une classe Printer, qui contient une interface pour imprimante. Il n’est
donc pas possible de définir une classe Rectangle, qui puisse hériter les propriétés de ces deux classes.
GeometricalObjet
Printer
Rectangle
Figure 11 : Héritage multiple n’est pas possible en Java
Ce problème peut être résolu à l’aide des interfaces (héritage d’interface). Une interface est une forme spéciale
de classe, qui ne contient que les déclarations des méthodes et des constantes mais pas leurs implémentations
(comme une classe abstraite, avec comme différence que cette dernière peut contenir des implémentations de
méthode).
Remarque pour les programmeurs C++. L’héritage multiple est soutenu dans C++. Par conséquent, C++ ne
connaît pas les interfaces.
La syntaxe pour définir une interface est la suivante :
public interface Printer
{
void method1();
}
La syntaxe de la classe qui implémente l’interface est la suivante :
public class Name implements InterfaceName1, InterfaceName2
{
// Implementation of the interfaces:
void method1()
{
...
}
...
}
Version 1.0, 05.03.07
Page 60
Introduction à la programmation Java
Introduction à la POO avec Java
Les interfaces possèdent les propriétés suivantes :
• Interfaces contient des méthodes et des constantes abstraites. Ces dernières définissent l’interface.
• Une classe, qui implémente une interface, doit implémenter toutes les méthodes ce cette interface.
• Une classe, qui implémente une interface, est alors du même type que cette interface.
• Les classes dérivées peuvent également implémenter les interfaces.
• Les interfaces peuvent être héritées.
• Une classe peut implémenter plusieurs interfaces. Ces interfaces doivent être définies à la suite du mot clé
implements, séparée par des virgules
UML :
Une interface est représentée comme une classe. La flèche entre l’interface et l’implémentation est toutefois
représentée en trait tillé.
A
B
Figure 12 : La classe B implémente l’interface A
Exemple :
L’exemple de l’introduction de ce chapitre doit être modifié : Une classe Rectangle hérite les propriétés de
la super classe GeometricalObjet (voir chapitre 3.4.3) et implémente en même temps l’interface
« Printer ».
abstract
GeometricalObject
x_coord
y_coord
isVisible
GeometricalObject()
setCoord()
draw()
move()
area()
Rectangle
width
height
Rectangle()
area()
getWidth()
getHeight()
abstract
Printer
style
print()
feedPaper()
Figure 13 : Exemple pour interface
L’exemple suivant ne contient pas le code pour la classe GeometricalObject. En effet, ce dernier reste
identique à celui du chapitre 3.4.3.
// Declaration of the Interface
public interface Printer
{
public void print(String str);
public void feedPaper();
}
Version 1.0, 05.03.07
Page 61
Introduction à la programmation Java
Introduction à la POO avec Java
public class Rectangle extends GeometrischesObjekt implements Printer
{
// Attribute
protected double width;
protected double height;
// Constructor
Rectangle (double x, double y, double width, double height, boolean isVisible)
{
super(x, y, isVisible);
this.width = width;
this.height = height;
}
// Method
public double area() {return(width * height);}
public double getWidth() {return(width);}
public double getHeight() {return(height);}
// Implementation of the interface
public void print(String str)
{
System.out.println(str);
}
public void feedPaper(){};
}
// Application for test
public class TestInterface
{
public static void main(String[] args)
{
// Instanciate the object
Rectangle rectangle = new Rectangle (1,3,10,5,true);
// Print the area
rectangle.print("Area of rectangle: " + rectangle.area());
}
}
L’impression dans ce programme de test ne s’effectue pas sur imprimante mais sur écran :
Area of rectangle: 50.0
Remarque: Dans cet exemple, il est également possible que la super classe GeometricalObject implémente
l’interface Printer (ce qui est même recommandé). Ainsi, toutes les sous classes de GeometricalObject
aurait également la méthode print().
3.7 Les paquets
Un paquet (package) est une collection de différentes classes avec des fonctions semblables. Les paquets sont
utilisés essentiellement dans des projets de plus grande importance, afin d’y améliorer la structure du
programme. En cas de nécessité, des sous paquets peuvent également être définis.
Les raisons suivantes justifient l’utilisation des paquets :
• Ils une structure plus claire en rassemblant différentes classes.
• Ils permettent d’identifier les classes dans des très grands projets.
• Ils contrôlent la visibilité des classes, des méthodes et des attributs dans un projet.
Version 1.0, 05.03.07
Page 62
Introduction à la programmation Java
Introduction à la POO avec Java
Les classes et les paquets peuvent être adressés de la manière suivante :
packagename.classname
Ou :
packagename.subpackagename.classname
Important:
Les noms des paquets et des sous paquets correspondent toujours aux noms des répertoires, qui contiennent les
fichiers du type classe de ces derniers. Ainsi le paquet « java.awt.image » se trouve dans le répertoire
« java\awt\image ». La recherche de ces fichiers s’effectue toujours relatif au répertoire d’installation (par
exemple « c:\java.1.4.2\bin »), dont le chemin d’accès est déposé dans les variables d’environnements
CLASSPATH.
3.7.1 Utilisation et importation
Avant de pouvoir utiliser une classe, il faut définir le paquet qui la contient de la manière suivante :
1) Indication du nom complet de la classe, paquet et éventuellement sous paquets inclus.
2) Importation de la classe au début de code avec le mot clé import.
3) Importation du paquet complet au début de code, également avec le mot clé import.
3.7.1.1 Indication du nom complet de la classe
La classe est utilisée directement dans le programme avec l’indication de son nom en complet, paquet et
éventuellement sous paquets :
Package.Class variable = new Package.Class();
Ou :
Package.Subpackage.Class variable = new Package.Subpackage.Class();
Exemple :
public class Date01
{
public static void main(String[] args)
{
java.util.GregorianCalendar date = new java.util.GregorianCalendar();
System.out.println(date.getTime());
}
}
Affichage sur l’écran:
Mon Feb 23 09:08:46 CET 2004
3.7.1.2 Importation de la classe au début du code
La classe est importée au début du programme avec le mot clé import, en idiquant son nom complet :
Exemple:
// Importation of the class
import java.util.GregorianCalendar;
public class Date02
{
public static void main(String[] args)
{
GregorianCalendar date = new GregorianCalendar();
System.out.println(date.getTime());
}
}
Version 1.0, 05.03.07
Page 63
Introduction à la programmation Java
Introduction à la POO avec Java
3.7.1.3 Importation du paquet au début du code
Le paquet contenant la classe est importé au début du programme avec le mot clé import. Cette variante exige
moins visibilité de la part du programmeur. Elle ne demande également pas de mémoire, car la recherche de la
classe ne s’effectue qu’au démarrage du programme.
Exemple:
// Importation of the package
import java.util.*;
public class Date03
{
public static void main(String[] args)
{
GregorianCalendar date = new GregorianCalendar();
System.out.println(date.getTime());
}
}
3.7.2 Les paquets mis à disposition par Java
La bibliothèque standard de J2SDK fournit de nombreuses classes, qui sont réparties sur plus de 20 paquets. Les
paquets les plus importants sont les suivants :
java.applet
java.awt
java.io
java.lang
java.net
java.util
Implémentation des applets
Interfaces graphiques
Entrées et sorties standards et avec les fichiers
Eléments généraux du langage, est importé implicitement au début de chaque classe
Pour les applications en réseaux
Pour l’utilisation des structures de données (calendrier, tabelle de Hash etc.)
3.7.3 Définition des paquets propres
Les paquets propres peuvent être définis de la manière suivante :
1) Choix d’un nom significatif pour le paquet (nom doit commencé avec une minuscule)
2) Création de la structure de répertoire correspondante
3) Définition au début de chaque fichier (avec le mot clé package) du nom du paquet, auquel appartient la
classe
Exemple :
Il faut définir une classe Test_A dans le paquet « package1 ». Une seconde classe Test_B doit être
également définie dans le sous paquet « package1_subpackage1 ». L’application est définie dans le
répertoire principal dans le fichier « Test.java ».
La structure du répertoire est la suivante :
Version 1.0, 05.03.07
Page 64
Introduction à la POO avec Java
Introduction à la programmation Java
PackageTest.java
package1
Test_A.java
package1_subpackage1
Test_B.java
Fichier PackageTest.java:
// Importation of packages and subpackages
import package1.*;
import package.subpackage1.*;
public class PackageTest
{
public static void main(String[] args)
{
// Instantiate and call object a of Test_A
Test_A a = new Test_A();
a.sayHello();
// Instantiate and call object of Test_B
new Test_B().sayHello();
}
}
Fichier Test_A.java:
package package1;
public class Test_A
{
public void sayHello()
{
System.out.println("My name is Bond, ");
}
}
Fichier Test_B.java:
package package1.subpackage1;
public class Test_B
{
public void sayHello()
{
System.out.println("James Bond");
}
}
Le paquet par défaut
Le paquet par défaut est utilisé avec les classes, qui n’ont pas été attribué à un paquet. Toutes les classes,
appartenant au paquet par défaut, peuvent être utilisées sans que cela soit spécifié explicitement.
Version 1.0, 05.03.07
Page 65
Introduction à la POO avec Java
Introduction à la programmation Java
3.7.4 Visibilité
La visibilité en fonction des mots clés public, protected et private a également été décrite à la Figure 3
pour les paquets. Pour résumer il existe deux possibilité d’attacher une classe B à la classe A :
1) Soit A et B appartient au même paquet
2) B a été déclaré comme public
Les deux classes se trouvent dans le même paquet avec l’utilisation des paquets par défaut. Ce qui économise la
déclaration public.
3.8 Le design OO
3.8.1 UML
Plusieurs tentatives pour essayer de définir une méthode de représentation de systèmes software orienté objet ont
été effectuées jusqu’à la deuxième moitié des années 90. Les méthodes les plus connues étaient celles de Grady
Booch, Ivar Jacobson et Jim Rumbaugh, qui ont essayé de définir indépendamment leur méthode de
représentation. La société Rational Rose réussi alors d’engager ces trois « amigos », pour qu’ils essayent
d’unissent leur méthode de représentation. Il en résulte alors le langage de modélisation unifié (en anglais :
Unified Modeling Language, et abrégé par : UML), qui est une méthode pour décrire des systèmes universels
(non seulement des systèmes software) de manière formelle.
UML permet de visualiser un système de différentes manières. Les représentations, les plus importantes pour le
développement des programmes, sont les suivantes :
• Vision de l’utilisateur modèle use-case
• Vision de la structure statique du programme Diagrammes des classes
• Vision du système dynamique Diagrammes d’état et de séquence
Les diagrammes de classe ont été introduits dans les chapitres précédents. Un résumé se trouve au chapitre 3.5.
Les chapitres suivants traitent la représentation des paquets et les diagrammes de séquence.
3.8.1.1 Les paquets
Les diagrammes des paquets sont utilisés pour représenter la hiérarchie des paquets et notamment leur
emboîtement (Subpackages).
Un diagramme des paquets peut être défini de la manière suivante :
Package 2
Package 3
Package 1
Relation de
compilation
Package 4
Class 1
Class 2
Package 4
Héritage
Class 3
Figure 14 : Diagramme des paquets
Version 1.0, 05.03.07
Page 66
Introduction à la POO avec Java
Introduction à la programmation Java
3.8.1.2 Les diagramme de séquence
Les diagrammes de séquence permettent une vision dynamique du système. Les diagrammes de séquences
montrent l’ordre dans lequel les objets appèlent les autres objets.
Object1:Class
name
Object2
Object3
Object4
1. event
2. operation
3. operation
(parameter list)
4. operation
(parameter list)
5. operation
Figure 15: Diagramme de séquence
Les diagrammes de séquence possèdent 2 dimensions. L’axe verticale représente normalement le temps. Les
poutres grises illustrent la durée de vie des objets. Les différents objets sont représentés sur l’axe horizontal. Les
appels mutuels des objets sont représentés par des flèches.
Version 1.0, 05.03.07
Page 67