Vous êtes sur la page 1sur 49

Conservatoire

National des Arts et

Le langage Java

Examen probatoire – Informatique – Mai


99
(version corrigée)

Jacqueline Deschamps
Président du jury : Professeur Christian Carrez
S O M MAI R E
INTRODUCTION 3

1. JAVA : UNE ÉTAPE DANS L’ÉVOLUTION DES LANGAGES DE PROGRAMMATION 4

1.1. L’ORIGINE 4
1.2. JAVA : LE LANGAGE DU TROISIÈME MILLÉNAIRE ? 4
1.3. L’ÉVOLUTION DES LANGAGES DE PROGRAMMATION 6
1.4. CE QU’ON ATTEND AUJOURD’HUI D’UN LANGAGE DE PROGRAMMATION 8
1.5. LE LANGAGE JAVA : POURQUOI FAIRE ? 9

2. LA DESCRIPTION DU LANGAGE JAVA 10

2.1. LA TECHNOLOGIE OBJET EN JAVA 10


2.2. LA CONSTRUCTION D’UN PROGRAMME JAVA 19
2.3. LA SYNTAXE DE JAVA 19
2.4. LES « APPLETS » 22
2.5. LES INTERFACES GRAPHIQUES 24
2.6. LES ENTRÉES-SORTIES 28
2.7. LA GESTION DES EXCEPTIONS 31
2.8. LA GESTION DES PROCESSUS MULTIPLES LÉGERS « THREADS » (ACTIVITÉS) 33
2.9. LA COMMUNICATION RÉSEAU 36
2.10. LES ÉVOLUTIONS RÉCENTES DE JAVA 36
2.11. LES ENVIRONNEMENTS DE DÉVELOPPEMENT JAVA 40

3. LES AVANTAGES ET LES INCONVÉNIENTS DU LANGAGE JAVA 41

3.1. ELÉMENTS DE COMPARAISON AVEC C++ 41


3.2. TABLEAU DE SYNTHÈSE 43

CONCLUSION 45

BIBLIOGRAPHIE 46

TABLE DES MATIÈRES 47

CNAM – Examen probatoire – mai 1999 – le langage Java – page 2 / 49


Introduction
Le langage Java est un langage récent. En 1995, James Gosling, de la société Sun Microsystem,
présentait son nouveau langage de programmation orienté objet au Sunworld à San Fransisco. En
décembre 1998, Sun annonçait la plate-forme Java 2, attendue sous le nom de JDK 1.2 (Java
Developpement Kit). A peine quatre années se sont écoulées durant lesquelles, Java a fait son
entrée dans le monde Internet d’abord avec les « applets », puis du côté des serveurs d’application
avec les JavaBeans, véritables briques pour la construction de logiciels, et les EJB (Enterprise Java
Beans), destinés à faciliter le développement de serveurs d’application. Lotus Notes a annoncé sa
première suite bureautique « made in Java », IBM, Oracle, et d’autres ont pris une licence Java…

Le langage Java a donc pénétré rapidement dans le monde des entreprises. C’est un vrai langage
orienté objet. Certains disent qu’il réunit l’ensemble des avantages de Smalltak et de C++. Il a
encore des problèmes de performance à résoudre. Sa pureté et sa richesse conceptuelle, son
indépendance vis à vis des matériels et systèmes, peuvent faire souhaiter son développement et sa
consolidation comme « le langage du troisième millénaire ».

En 1995, Java fut donné à la communauté Internet. Sun, en mettant à disposition sur le Web le
compilateur, les spécifications, les bibliothèques et la documentation permettait au Monde entier de
développer dans un environnement non-propriétaire. Les spécifications du langage Java sont en
cours de soumission aux instances de normalisation de l’ISO. La normalisation pourrait être une
garantie pour que les spécifications du langage évoluent sans recréer des systèmes propriétaires.
Java fait, en effet, l’objet d’une intense bataille industrielle qui s’est exprimée sur le terrain
juridique avec le procès de Sun à l’encontre de Microsoft. Au-delà de l’aspect commercial, c’est
l’intérêt des utilisateurs qui est en jeu.

Le présent rapport expose d’abord les raisons qui ont poussé à la création du langage Java et
survole ses principales caractéristiques.

Dans une deuxième partie, il résume, face à l’évolution des technologies, ce que les utilisateurs
attendent d’un langage de programmation, les principaux critères d’un bon langage et l’apport les
langages orienté objet.

Puis, il analyse de façon plus détaillée le fonctionnement du langage Java et met en avant comment
celui-ci répond aux besoins.

Enfin, après une rapide comparaison avec C++, il résume les principaux points forts et points
faibles du langage Java en prenant en compte le contexte d’utilisation.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 3 / 49


1. Java : une étape dans l’évolution des langages de programmation

1.1. L’origine
Java est né comme langage de programmation pour réaliser des petits logiciels intégrés dans les
appareils électroniques « grand public ». Ces logiciels doivent respecter un certain nombre de
contraintes, telles que : pouvoir tourner sur de nouvelles puces dès qu’elles arrivent sur le marché
et posséder une grande fiabilité.

L’objectif initial était donc la création d’un langage pour le développement des applications de
contrôle d’équipements domestiques. Il devait être indépendant des plates-formes, robuste et sûr.

Une petite équipe de Sun, James Gosling, Arthur Van Hoff et Bill Joy, a constaté que les langages
existants tels que C et C++ n’étaient pas adaptés pour produire des logiciels capables de respecter
ces contraintes : d’une part, le code compilé ne pouvait fonctionner que sur un seul type de puce et
d’autre part la complexité de C ou C++ rendait l’écriture de logiciels fiables particulièrement
délicate.

En 1990, Gosling, Sheridan et Naughton se lancèrent dans la conception d’un nouveau


langage dénommé Oak. Ce langage était simple, fiable et indépendant de l’architecture.

En 1993, le Web se développa de façon soudaine et très importante. Les contraintes respectées par
Oak correspondaient bien aux développements d’applications sur Internet. Sun lança alors le
langage Java qui permet de développer les « applets ». Les « applets » ou appliquettes en français
sont de petits programmes inclus dans des documents HTML qui s’exécutent lors de l’affichage de
la page. Elles permettent d’animer les pages HTML et de les rendre davantage interactives.

En mai 1995, Le langage Java est présenté lors d’une conférence et mis à disposition des
développeurs avec ses spécifications, un environnement de développepent le JDK (java
Developpement Kit) et des bibliothèques d’objets sur le Web.

1.2. Java : le langage du troisième millénaire ?


Java est donc un langage de programmation orienté objet. Il est gratuit. Java est aussi une marque
qui regroupe trois notions :

 un langage, objet principal du présent rapport,


 une machine virtuelle JVM (Java Virtual Machine) qui permet d’interpréter et
d’exécuter les programmes Java. C’est l’existence de la JVM qui permet
l’indépendance vis à vis des plates-formes.
 des API (interface de programmation d’applications) : c’est un ensemble de
classes avec une documentation d’utilisation qui accompagnent le langage et
permettent de réutiliser des composants déjà testés.
Dans un document de Sun « The Java language : A White Paper » Java est défini comme suit :

« un langage simple, orienté objet, distribué, interprété, robuste, sécurisé,


indépendant des architectures, portable, efficace, multi « threads » et dynamique »

Document de Sun cité dans Java in a Nutshell - Davis Flanagan – édition O’REILLY

Simple
Java a été conçu pour être un langage simple à apprendre. Il contient un nombre limité de
constructions. Il n’utilise pas de pointeurs. C’est le langage qui gère l’attribution et la suppression

CNAM – Examen probatoire – mai 1999 – le langage Java – page 4 / 49


des emplacements mémoires nécessaires aux programmes libérant ainsi le programmeur des
fonctions de plus bas niveau, proches de la machine.

Java utilise beaucoup de constructions de C ou de C++ et a une syntaxe très proche de ces
langages. Ceci le rend familier aux programmeurs C et C++.

Orienté objet
A la différence de C++, Java a été entièrement conçu pour être orienté objet. Les données et
méthodes sont encapsulées dans un même objet qui constitue un composant logiciel. En Java tout
est objet, exceptions faites des types primitifs pour les valeurs numériques, des caractères et des
booléens. Il est livré avec un ensemble de classes, organisées en paquetages qui sont utilisés dans
les programmes. Il existe ainsi un paquetage pour les interfaces graphiques (java.awt), un pour les
entrées/sorties (java.io), un autre pour les applications en réseau (java.net)…

Réparti
Java est conçu pour le développement d’applications en réseau. Avec Java, il est aussi facile
d’ouvrir un fichier sur une machine distante que sur une machine locale. Il est également possible
de créer des applications client/serveur.

Interprété
Le code source Java est d’abord compilé pour générer du « byte code » et non directement du code
machine. Le byte-code est ensuite interprété et exécuté par une « Java Virtual Machine » (JVM).

L’avantage de la compilation est de générer un code optimisé pour s’exécuter sur une machine.
L’inconvénient est que ce code est dédié à un seul type de machine. L’avantage du byte-code de
Java est qu’il est indépendant des plates-formes. Son inconvénient est d’être plus lent à l’exécution.

Java est un bon compromis entre les techniques de compilation et d’interprétation : Il est
partiellement compilé ce qui permet d’obtenir des temps d’exécution corrects et partiellement
interprété pour être indépendant des plates-formes.

Robuste
Java a été conçu pour être un langage permettant de développer des applications fiables. Il élimine
un certain nombre de causes de bogues.

Il est fortement typé et oblige le programmeur à déclarer toutes les méthodes. Les erreurs sont ainsi
plus souvent détectables à la compilation. Le modèle de représentation de la mémoire adopté par
Java contribue à la fiabilité des logiciels.  Il n’autorise pas les pointeurs, on ne peut donc pas
écraser des données ou corrompre la mémoire. Il a prévu un « ramasse miettes » qui limite les
bogues liées à la gestion de la mémoire dynamique.

Sûr
Le langage Java implémente un certain nombre de mécanismes de sécurité pour protéger
l’utilisateur de la malveillance et de la maladresse qui pourraient aboutir à endommager des fichiers
ou créer des virus. Cette caractéristique est particulièrement importante pour l’échange
d’appliquettes et de tous types de composants logiciels à travers les réseaux, en particulier
l’Internet.

La sécurité de Java est renforcée par sa robustesse, en particulier par le modèle adopté pour la
gestion de la mémoire. Le run-time de Java alloue la mémoire.

Indépendant de l’architecture et portable


Le byte-code généré par le compilateur Java est indépendant de l’architecture. Il peut donc tourner
sur toutes les plates-formes implémentant la JVM (Java Virtual Machine).

CNAM – Examen probatoire – mai 1999 – le langage Java – page 5 / 49


Java s’assure que rien dans les spécifications du langage, n’est dépendant de l’implémentation
(taille des types primitifs et comportement des opérations qui leur sont associées, par exemple).

L’environnement de Java (compilateur, run-time) est également portable.

Efficace
L’interprétation du byte-code ne produira jamais un résultat aussi efficace que du C compilé. Pour
certaines applications, cette faible performance n’est pas un handicap.

Pour améliorer les performances, on a créé des compilateurs « just-in-time » capables de compiler
le byte-code en code machine en cours d’exécution.

Permet la synchronisation des processus (« threads »)


La programmation de processus agissant de façon simultanée est utilisée pour améliorer les
performances des applications graphiques interactives.

Java met à la disposition des programmeurs la classe Thread dans le paquetage java.lang. Elle
comporte des méthodes pour démarrer, exécuter, contrôler, stopper l’état d’un processus.

Java dispose également de primitives de synchronisation qui permettent de préciser que certaines
méthodes ne pourront être utilisées de façon concurrente.

Dynamique
Java peut charger des classes en cours d’exécution « just in time ». Contrairement à C++, si un
objet est transmis au programme, il peut déterminer sa classe, grâce à une représentation
consultable en cours d’exécution.

1.3. L’évolution des langages de programmation


1. L’assembleur
Les premiers ordinateurs étaient programmés en langage directement compréhensible par le
processeur. Le premier langage élaboré a été l’assembleur. Par rapport au langage machine, il a
apporté deux types d’amélioration : il utilisait des mnémoniques pour les instructions machines et il
masquait la complexité de certaines opérations, par exemple : l’adressage. La programmation en
assembleur nécessite de bien connaître la machine sur la quelle on travaille.

2. Les langages évolués


Les langages d’assemblage étaient encore très proches de la machine, certains ont alors imaginé
des langages évolués, qui seraient proches du langage naturel et indépendant de la machine. Un
langage de programmation évolué permet d’écrire des instructions longues et complexes très
éloignées des structures de la machine et proches des habitudes humaines.

Pour effectuer le calcul suivant :

C  (4 * A + 5 * B) * (C + D)

La solution en assembleur sera


TAC 30 transfert de C (adresse 30) dans un registre
ADD 40 addition de C avec D (40 est l’adresse de D)
TME 70 stockage provisoire de C + D à l’adresse 70
TAC 10 transfert de A (adresse 10) dans un registre
MUL 50 multiplication de 4 par A
TME 80 stockage provisoire de 4 * A à l’adresse 80
TAC 60 transfert de B (adresse 60) dans un registre
MUL 20 multiplication de 5 par B

CNAM – Examen probatoire – mai 1999 – le langage Java – page 6 / 49


ADD 80 addition de 5 * B à 4 * A
MUL 70 multiplication de (5 * B + 4* A) par (C + D)
TME 30 rangement du résultat en C (adresse 30)
FIN

En Cobol, la solution tient en une ligne d’instructions.


COMPUTE C = (4 * A + 5 * B) * (C + D)

Dans les décennies 1950, 1960 et 1970 beaucoup de langages de programmation ont été créés.

1.3.1.1. Parmi les premiers langages évolués :


FORTRAN (1954) : adapté aux calculs numériques et à la résolution de problèmes,

COBOL (1959) : adapté aux applications de gestion, il facilite la gestion des fichiers.

1.3.1.2. Parmi les langages structurés :


ALGOL (1958) : langage structuré, il introduit la notion de blocs imbriqués et de récursivité,

PL/I (1964) – créé par IBM : il reprend certaines formes d’ALGOL pour les traitements et les
facilités de Cobol pour la gestion des fichiers.

Pascal (1970) : s’inscrit dans la tradition des langages ALGOL. Il s’appuie sur la notion de
variables. Il est très fortement structuré.

ADA (1975) : lancé par le département de la défense américaine (DOD). Il reprend les notions de
modularité et de types de variables de Pascal.

1.3.1.3. Parmi les langages fonctionnels :


Lisp (1958) : il fait partie des langages dits fonctionnels par opposition au langage algorithmique.

3. Le sens de l’évolution
Les langages de programmation ont évolué selon les caractéristiques suivantes :

 le domaine des applications à développer (Cobol pour la gestion, Fortran pour le calcul
scientifique) avant de considérer qu’un langage devait être adapté à tous types
d’application (ALGOL),
 la recherche de gain de temps de programmation. Le langage se veut de plus en plus
proche de la pensée de l’homme. Mais, le niveau d’abstraction des langages évolués
demande encore aux programmeurs de penser dans les termes de la machines et non
dans celui des problèmes à traiter,
 la facilité de maintenance des programmes : lisibilité et maîtrise. Ce qui a donné
naissance à la programmation structurée avec des fonctions et des emboîtements de
fonctions. La lecture du code devenait plus facile,
 la fiabilité des programmes : déclaration de variables et de fonctions permettant aux
compilateurs de repérer un plus grand nombre d’erreurs,
 la recherche d’une standardisation.

4. L’évolution du contexte
Dans le même temps, les domaines couverts par les applications informatiques se sont étendus. Des
applications scientifiques vers la gestion des entreprises, les applications industrielles, celles d’aide
à la décision et de communication.

Les ordinateurs gagnaient considérablement en puissance. La micro-informatique s’est développée,


Internet a explosé.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 7 / 49


Les utilisateurs de l’informatique ont changé : des chercheurs, on est passé aux personnels de
l’entreprise, puis au grand public. Leur nombre a considérablement augmenté, leurs exigences se
sont affirmées.

5. Les langages « orienté objet »


Dans ce contexte, l’évolution des langages de programmation se poursuit avec l’intégration des
concepts d’orienté objet.

Les besoins de l’informatique d’aujourd’hui sont :

 la capacité de coopération de systèmes hétérogènes,


 le partage des ressources sur des réseaux distants, l’autonomie et la puissance
du poste de travail, en même temps que la multiplication des postes de travail,
 l’utilisation d’interfaces graphiques et du multimédia,
 des langages de programmation de plus en plus proches de notre
représentation mentale afin de traiter des problèmes de plus en plus
complexes,
 la ré-utilisabilité de composants logiciels et la possibilité d’évolution
incrémentale des applications.
La technologie orientée objet tente de répondre à ces besoins. Cette technologie est composée de
trois catégories d’outils qui se complètent : les méthodes, les langages et les systèmes de gestions
de bases de données orientées objet (SGBDOO).

Les langages orienté objet font un pas en avant dans l’abstraction en proposant aux programmeurs
des outils pour penser dans l’espace du problème. Parmi eux, on peut en citer deux langages qui ont
inspiré Java : Smalltallk à qui Java a emprunté un certain nombre de concepts et C++ dont la
syntaxe est très similaire à celle de Java.

Smalltalk est le premier langage orienté objet. Il a été créé au début des années 1970 par Goldberg
à Xerox Park. Il est conçu autour de cinq concepts fondamentaux que l’on retrouve dans le langage
Java : objets, messages, méthodes, classes et instances. L’originalité du langage réside dans la
généralisation du concept d’objet : une classe est elle-même un objet. Elle est, en tant qu’objet, une
instance d’une classe formant sa méta classe. Pour éviter la boucle infinie, on définit une classe
particulière appelée Méta classe, racine du système. Comme Java, Smalltalk possède une riche
bibliothèque de classes prédéfinies favorisant ainsi la ré-utilisabilité.

Le langage C++ - développé au centre de recherche de Bell Lab de ATT par Stroustrup - est un
langage hybride qui étend le langage C par les concepts de types abstraits de données : classe et
sous classe, d’héritage, de polymorphisme et de liaison tardive. C’est le langage orienté objet le
plus utilisé aujourd’hui. Il a des avantages : performance et portabilité ; mais présente aussi des
inconvénients : il est impur, car l’encapsulation n’est pas toujours respectée, les programmes C
sont faiblement lisibles et la gestion de la mémoire se fait par un « ramasse miettes » manuel.

1.4. Ce qu’on attend aujourd’hui d’un langage de programmation


6. La fiabilité des logiciels produits
Avec l’augmentation du nombre des utilisateurs, les problèmes de déploiement des applications et
de leur maintenance deviennent cruciaux. La probabilité d’occurrence des pannes est liée à la
complexité des logiciels et les pannes logicielles sont le plus souvent dues à des erreurs de
conception. Parmi les solutions permettant de limiter le nombre de ces pannes, une conception
idoine du langage de programmation est de première importance. Celui-ci doit intégrer une
diminution des risques d’erreurs. En effet, si le langage est fortement structuré et impose, par
exemple, la déclaration de toutes les méthodes, un plus grand nombre d’erreurs sera détecté lors de
la compilation. Si le langage n’autorise pas les pointeurs, s’il exclut le débordement des tableaux, il

CNAM – Examen probatoire – mai 1999 – le langage Java – page 8 / 49


n’y aura pas de risque d’écrasements de données ou de zones mémoires sensibles. Si le langage
libère la mémoire, il n’y aura pas de « fuites mémoires ». S’il gère de façon systématique les
exceptions et les erreurs, le nombre de bogues diminuera inévitablement.

7. La standardisation et l’indépendance vis à vis des plates-formes


La multiplication des plates-formes : UNIX et ses différentes versions, Windows 95 et Windows
NT et le powerPC de Mac…. est une donnée de l’équipement de la plupart des entreprises. Le
langage de programmation peut permettre l’indépendance du code source mais aussi du code
compilé vis à vis des matériels et systèmes d’exploitation.

8. La ré-utilisabilité et la richesse des bibliothèques


Elle permet de gagner du temps de développement et d’augmenter la fiabilité des logiciels. Elle
pose deux questions : quel est le taux d’invariance des objets ? Comment retrouver facilement un
objet parmi les milliers ou des dizaines de milliers d’objet disponibles ?

Le succès des langages orienté objet est accru par le fait qu’ils incorporent non seulement un
langage avec des concepts, une syntaxe et un compilateur mais qu’ils incluent une bibliothèque
d’objets bien décrits et faciles à utiliser. La pertinence du classement des bibliothèques est
essentielle dans le choix d’un langage. La granularité des composants mis à disposition est
également à prendre en compte.

9. La souplesse des représentations


Le langage doit permettre au programmeur de se consacrer à l’essentiel : la représentation des
problèmes qu’il a à traiter. Il doit donc le libérer des aspects les plus proches de la machine.

Un langage doit être simple et riche en même temps. Cela peut sembler contradictoire. Mais, c’est
pourtant, semble-t-il, le cas de Java. Le langage réduit au maximum les méthodes natives, mais il
est extensible à l’infini. Pour l’enrichir, il suffit de créer une nouvelle classe.

10. La simplicité et rapidité de programmation


Le temps passé à la programmation et à la formation des programmeurs est important. Un langage
simple à apprendre pour le programmeur est un garant de la qualité des applications. Un langage
qui permette de réduire les développements permettra une économie importante pour l’entreprise.

11. La performance des logiciels


Les objets manipulés par les applications demandent de plus en plus de ressources. La rapidité
d’exécution des programmes est impérative pour certaines applications.

1.5. Le langage Java : pourquoi faire ?


Le langage Java, dans un premier temps, a été utilisé pour les appliquettes et applications clientes.
Cependant, l’opposition entre Sun et Microsoft et la difficulté de maintenir la Machine Virtuelle
sur un PC ont limité la pénétration de Java dans ce domaine. Avec la fusion AOL-Netscape et son
partenariat avec Sun, un retour en force de Java sur le poste client est possible.

Sun intègre dans sa stratégie, le développement de Java pour des applications embarquées sur les
téléphones mobiles, les agendas personnels… un marché très large.

Java a ensuite pénétré dans le monde des logiciels serveurs grâce, en partie, à la coalition Netscape,
Oracle, IBM et Sun regroupés dans Noïse. Une trentaine de produits serveurs d’applications Java
sont apparus dans les 18 derniers mois dont Visual Age 2.0 d’IBM, Jbuilder 2 d’Inprise (racheté
par Oracle), Power J 2.5 de Sybase, Visual Café 2.0 de Symantec, Vision Software de Vision Jade.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 9 / 49


Parallèlement au succès qu’il rencontre dans les entreprises, le langage Java est introduit à
l’université et dans les grandes écoles pour la formation informatique.

L’enjeu autour de la pénétration du langage Java n’est pas seulement commerciale. Les utilisateurs
attendent que l’informatique se mette réellement à leur service. Le succès de Java dans les
entreprises s’explique par la prise en compte de leurs besoins. La tentative de créer un nouveau
standard avec les Enterprise Java Beans (EJB) répond à une demande croissante d’échange de
composants pour des applications serveurs critiques.

2. La description du langage Java

2.1. La technologie objet en Java


Dans le chapitre précédant, nous avons rappelé l’évolution des langages de programmation. Nous
avons constaté que les langages orienté objet semblent, aujourd’hui, le mieux répondre aux besoins
des utilisateurs. Nous allons maintenant rappeler les principaux concepts des langages orienté objet
et étudier leur mise en application dans le langage Java..

12. Les objets


2.1.1.1. Définition
L’objet, dans un langage de programmation, est une représentation d’un objet du monde réel. Cette
représentation est construite par abstraction : parmi les propriétés de l’objet réel, on extrait et l’on
retient celles qui sont essentielles au regard du problème considéré.

L’objet est une entité informatique complète. Avant la technologie objet, les systèmes
informatiques séparaient les données et les procédures traitant ces données. Dans l’orientation
objet, il n’existe plus qu’un seul type d’entité informatique : l’objet. Il est un composant logiciel.

L’objet possède donc à la fois une partie statique, qui représente son état et les liens qui l’unissent
aux autres objets, et une partie dynamique qui décrit son comportement, c’est à dire l’ensemble des
opérations qui lui sont applicables. Un objet émet et reçoit des événements du milieu dans lequel il
se trouve.

L’objet a une identité. Celle-ci est indépendante de la valeur associée à l’objet. Elle est gérée par le
système.

Un objet est donc défini par : une identité, un état et un comportement.

2.1.1.2. L’objet dans le langage Java

Un exemple d’objet :

Cercle c ; // Définit la référence (ou handle)correspondant à c


c = new Cercle () ; // Création d’un objet, instance de la classe cercle
double a ;
c.rayon = 1,5 ;
a = c.surface () ;

L’objet, identifié par sa poignée ou « handle » c, permet de représenter un cercle, c’est une
abstraction : parmi ses caractéristiques, nous avons conservé ici sa taille et le calcul de sa surface. Il
a une identité qui le référence de façon unique : l’identité est gérée par le langage Java.
L’utilisateur connaît le nom de l’objet, ici c, et son contexte. L’objet appartient à la classe des
cercles dénommée Cercle.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 10 / 49


Il possède deux propriétés : une statique, la longueur de son rayon et l’autre dynamique, une
méthode permettant de calculer sa surface.

Pour copier un objet, il faut utiliser la méthode clone (). En effet, les types références (handle)
n’étant pas passés par valeur, affecter un objet « b » à un autre objet « a » a pour résultat d’attribuer
deux références au même objet et de perdre l’objet référencé par a.
Cercle a = new Cercle () ;
Cercle b = new Cercle () ;
a = b ;

Un objet Cercle Un autre objet Cercle

a b

a=b

Un objet Cercle Un autre objet Cercle

a b

Figure 1 : copier une référence n’est pas copier un objet

Dans le langage Java, tout est objet à l’exception des types numériques, des caractères et des
booléens.

Le « ramasse miettes » ou « garbadge collector »

Nous avons étudié la création des objets, mais comment les détruit-on ? Il n’existe pas en Java de
mots-clés pour détruire les objets lorsqu’ils ne sont plus utilisés. Java utilise une technique connue
sous le nom de « ramasse miettes » qui détecte automatiquement les objets qui ne sont plus utilisés
et les détruits. Cette technique était déjà utilisée par les langages Lisp et Smalltalk.

Comment le « ramasse miettes » détecte-t-il les objets qui ne sont plus utilisés ? Tout objet est créé
dans une zone mémoire appelée « tas » ou « heap ». L’identifiant de l’objet fait référence à son
adresse (handle) dans le tas. On ne peut directement modifier ce handle. Seul le « ramasse miettes »
peut détruire les objets, il le fait automatiquement lorsque l’objet n’est plus référencé. En effet,
l’interpréteur sait quels sont les objets qu’il a alloués, il sait quelles variables réfèrent quels objets,
et quels objets réfèrent quels autres objets. Il peut donc en déduire les objets qui ne sont plus
référencés par aucune variable ni aucun autre objet.

Le « ramasse miettes » de Java est utilisé par une activité ou « thread » de basse priorité. Cette
activité profite des temps morts où la machine attend, par exemple, une action de l’utilisateur pour
s’exécuter. Elle n’est donc pas pénalisante pour le système sauf dans le cas où celui-ci n’a plus de
mémoire disponible.

La persistance

Certains objets ne servent que durant l’exécution d’un programme, d’autres ont besoin d’être
conservés en dehors des temps d’exécution du programme. On dit qu’ils sont persistants. Il est

CNAM – Examen probatoire – mai 1999 – le langage Java – page 11 / 49


possible en Java de déclarer que des objets pourront être persistants, c’est à dire conservés dans des
fichiers, en implémentant leur classe par l’interface Serializable.

13. Les classes


2.1.1.3. Définition
Une classe contient un ensemble d’objets qui possèdent des propriétés statiques (ou de structure) et
dynamique (ou de comportement) communes. Une classe permet ainsi de spécifier, en les
factorisant, les attributs et les méthodes communes à un ensemble d’objets.

A l’aide de ce mécanisme, un objet n’est plus représenté que par le nom de sa classe et la valeur de
ses attributs. Lorsqu’il est stimulé, c’est à dire lorsqu’il reçoit un message invoquant une de ses
méthodes, celle-ci est trouvée dans une des classes à laquelle il appartient.

Les objets sont donc des occurrences ou instances d’une classe. Instancier une classe revient à créer
un nouvel objet ayant toutes les propriétés de cette classe.

La mise en évidence des classes à partir des objets ressort d’une des principales méthodes
d’approche d’un problème : la classification.

2.1.1.4. Les classes en Java

Un exemple : la classe Voiture

Class Voiture {
String marque ; // L’attribut marque de la classe String
String couleur ; // L’attribut couleur de la classe String
boolean etatMoteur ; // L’attribut etatMoteur de type boolean
void demarerMoteur () { // définition de la méthode demarerMoteur.
// « void » signifie que cette méthode ne rend pas de résultat
if (etatMoteur == true)
System.out.println (« Le moteur est déjà en marche ») ;
else {
etatMoteur = true ;
System.out.println (« Le moteur a été mis en marche) ;
}
}

La classe Voiture regroupe l’ensemble des objets qui sont des voitures. Toutes les voitures sont
définies par une marque et une couleur. Elles possèdent toutes une méthode qui permet de mettre
leur moteur en marche ou de le stopper.

Créer une instance de la classe Voiture

Si je veux représenter un nouvel objet qui est ma voiture, j’écrirais :


Voiture maVoiture = new Voiture() ;
/* Les parenthèses signifient un appel à une méthode de type constructeur
possédant le même nom que la classe – l’objet retourné est implicitement une
instance de la classe */
maVoiture.marque = « Renault » ;
maVoiture.couleur = « vert » ;
maVoiture.etatMoteur = false ;

L’objet est défini par sa classe et la valeur de ses attributs que l’on appelle aussi variables
d’instance. Les méthodes de la classe s’appliquent à tous les objets de la classe. Le rôle du
constructeur est de prendre en charge les initialisations pour le nouvel objet.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 12 / 49


Nous pouvons définir un ou plusieurs constructeurs dans la classe.
public Class Voiture {
String marque ; // L’attribut marque
String couleur ; // L’attribut couleur
boolean etatMoteur ; // L’attribut etatMoteur

// définition d’un premier constructeur


public Voiture (String marque, String couleur, boolean etatMoteur)
{
this.marque = marque ; // this désigne l’objet en cours
this.couleur = couleur ;
this.etatMoteur = false ;
}
void demarerMoteur () { // déclaration de la méthode demarerMoteur
if (etatMoteur == true)
System.out.println (« Le moteur est déjà en marche ») ;
else {
etatMoteur = true ;
System.out.println (« Le moteur a été mis en marche) ;
}
}

Avec le nouveau constructeur, je peux écrire :


Voiture maVoiture = new Voiture(« Renault »,  « vert », false) ;

Il peut y avoir plusieurs constructeurs et ils portent tous le même nom, ils sont différenciés par le
compilateur grâce aux arguments qu’ils utilisent. On parle alors de surcharge de méthodes.

Variables de classe

Il peut exister des variables de classe. Par exemple, si nous voulons savoir le nombre de voitures,
nous pouvons créer une variable nombre de la classe Voiture. Java n’autorise pas les variables
globales, toutes celles-ci doivent être déclarées à l’intérieur d’une classe. Une variable de classe est
précédée du mot-clé « static ».

Une variable de classe est déclarée comme suit :


static String nombre [] ; // nombre = nombre de voitures : variable de classe

Pour accéder à une variable de classe on écrira le nom de la classe suivi du point et du nom de la
variable de classe. Chaque variable de classe étant référencée par le nom de sa classe, il n’y a pas
de risque de conflit de nom.

Les constantes sont définies comme variables de classe particulières, avec les mots-clés static et
final.

Méthodes de classe

Il existe également des méthodes de classe. Elles sont déclarées en statique dans la classe. Les
méthodes de classe ne font pas de référence implicite à « this » qui désigne l’objet en cours.

14. L’encapsulation
2.1.1.5. Définition
L’encapsulation est un procédé qui consiste à masquer au client potentiel tout ce qui ne constitue
pas les caractéristiques essentielles d’un objet.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 13 / 49


Les données d’un objet sont privées au sens ou seules ses propres méthodes peuvent y accéder. Les
méthodes d’une classe sont privées au sens ou les classes contiennent elles-mêmes
l’implémentation de ces méthodes.

Tout accès aux données d’un objet - dans son rôle de serveur - passe par l’invocation de l’une de
ses propres méthodes. L’appel d’une méthode d’un objet passe par l’envoi d’un message à cet
objet. Le message est une demande d’exécution d’une des méthodes. Comme les données, les
objets peuvent être manipulés, mais ils permettent aussi de manipuler de l’information. Ils sont à la
fois client et serveur. Les objets émettent et reçoivent des messages.

Ainsi, toutes les données des objets sont entourées d’une capsule de méthodes, représentée par la
classe, qui est le passage obligé pour l’accès à ces données.

Les signatures des méthodes définissent l’interface de l’objet qui, seule, est visible aux yeux d’un
client potentiel.

2.1.1.6. L’encapsulation en Java


Le langage Java permet le respect de l’encapsulation.

Pour cacher des méthodes ou des variables de partout, il suffit de les déclarer comme étant privées.
Pour les rendre visibles de partout, on les déclarera publiques.

Il existe en fait quatre niveaux de visibilité des champs en Java : public, private, package et
protected. Ces spécificateurs s’appliquent aux variables comme aux méthodes.

Accessible par : public protected package private


La même classe OUI OUI OUI OUI
Les classes du même paquetage OUI OUI OUI NON
Les sous-classes d’un paquetage différent OUI OUI NON NON
Les non-sous-classes et d’un paquetage différent OUI NON NON NON
Figure 2 : visibilité des champs en Java (d'après Java un a nutshell")

Quelques Exemples :

Une définition de la classe Personne :


class Personne {
private String nom ;
private String societe ;
public void presenteToi () {
System.out.println (« je m’appelle » + nom) ;
System.out.println (« je travaille chez » + societe) ;
} ;
}

La définition d’un constructeur pour instancier les variables privées nom et société est nécessaire :
public Personne (String leNom, String uneEntreprise) {
nom = leNom.toUpperCase () ;
societe = uneEntreprise ;
}

Un message adressé à un objet du type Personne dénommé «  inconnu »


inconnu.presenteToi ()

La signature de la méthode presenteToi


public void presenteToi (Personne) ;

CNAM – Examen probatoire – mai 1999 – le langage Java – page 14 / 49


Personne

INTERFACE
-nom : String
presenteToi() -societe : String
+presenteToi()
personne(leNom : String, lEntreprise : String)

Classe

INTERFACE
Message
Attributs : type
Méthodes()

Figure 3 : représentation du principe d'encapsulation

15. L’héritage
2.1.1.7. Définition
Le concept d’héritage permet de définir une nouvelle classe d’objets à partir de tout ou partie d’une
ou plusieurs autres classes.

Une classe peut être définie comme une sous-classe d’une autre classe. Les instances de la sous
classe héritent automatiquement des propriétés de la classe mère. La sous classe spécialise la classe
mère par l’ajout ou la substitution d’attributs et de méthodes. Une super classe peut être définie, au
niveau conceptuel, par la généralisation de caractéristiques d’un ensemble d’autres classes qui
deviendront ses sous classes.

Une classe abstraite est une classe qui n’a pas d’instance. Seules ses sous classes pourront être
instanciées. Une classe abstraite est utilisée pour obtenir un niveau d’abstraction plus élevé et une
meilleure représentation de la réalité.

L’héritage peut être multiple, dans ce cas, la sous classe hérite de plusieurs classes. Elle possède
alors l’union des attributs et des méthodes de toutes les super-classes. Si des conflits se déclarent
entre les éléments hérités, alors il faut définir une méthode pour les résoudre. Une méthode consiste
à utiliser une liste de priorités de classe.

Une classe est donc définie par des attributs et des méthodes hérités et des attributs et des méthodes
propres.

2.1.1.8. L’héritage en Java


Le langage Java autorise la création d’une classe par l’extension d’une classe déjà existante. Ce
procédé permet de spécialiser une classe.

Exemple :

class Employe extends Personne {


int salaire ;
String departement ; /* ajout de deux variables d’instance aux propriétés
de la classe personne */

// méthode – ici constructeur - pour accéder aux variables d’instance


public Employe (int leSalaire, String leDepartement) {

CNAM – Examen probatoire – mai 1999 – le langage Java – page 15 / 49


this.salaire = leSalaire ;
this.societe =  leDepartement ;
}
}

Quand une classe est déclarée avec le modificateur « final », elle ne peut plus être étendue. Cela
permet au compilateur d’optimiser les invocations de méthodes d’instance.

Toutes les classes ont une super-classe, sauf une : la classe Object. La classe Object est la racine
de la hiérarchie des classes.

Les classes abstraites existent dans le langage Java. Par exemple, nous souhaitons créer une classe
abstraite « forme » qui désigne une forme graphique quelconque. Cette classe contiendra un certain
nombre d’autres classes : triangle, rectangle, cercle…, mais aucun objet forme. Les sous-classes
d’une classe abstraite peuvent être instanciées si elles ne sont pas elles-mêmes abstraites.

Les classes abstraites peuvent définir des méthodes abstraites. Celles-ci sont redéfinies dans les
sous-classes sauf si celles-ci sont elles-mêmes abstraites.

Exemple :

// déclaration de la classe abstraite et de la méthode abstraite surface


public abstract class Forme {
public abstract double surface () ;
}
/* déclaration de la classe cercle qui spécialise la classe abstraite Forme */
public class Cercle extends Forme {
protected double r ;
protected static final double PI = 3.14116 ;
public Cercle () { r = 1.0} ;
public Cercle ( double r) { this.r = r ; } 
public double surface () {return PI * r * r ; }
}

Il n’y a pas d’héritage multiple dans le langage Java. Mais les caractéristiques de celui-ci sont
possible grâce aux interfaces.

Une interface est une définition d’un ensemble de méthodes qu’un ou plusieurs objets peuvent
implanter. Une interface n’a pas de variables, elle ne déclare que des méthodes et des constantes.

Une interface ressemble beaucoup à une classe abstraite, le spécificateur « abstract class » est
remplacé par « interface ». Mais, alors qu’une classe abstraite peut définir des méthodes non
abstraites, toutes les méthodes de l’interface sont abstraites. Une classe qui implémente une
interface hérite de ses méhtodes abstraites. L’implémentation de celles-ci est fournies dans la
classe.

Exemple :

// Déclaration d’une interface Traçable


public interface Tracable {
public void setColor (Color c) ;
public void setPosition (double x, double y) ;
public void draw (DrawWindow dw) ;
}
// Implémentation une interface
public class RectangleTracable extends Rectangle implements Tracable {
// nouvelles variables d’instance
private Color c ;
private double x, y ;
// Un constructeur

CNAM – Examen probatoire – mai 1999 – le langage Java – page 16 / 49


public RectangleTracable (double l, double ll) { super (l, ll) }
// voici les implémentations de la méthode Tracable
// Nous héritons des méthodes de Rectangle
public void setColor (Color c) { this.c = c } ;
public void setPosition (double x , double y) { this.x = x ; this.y = y ;}
public void draw (DrawWindow dw) {dw.drawRect ( x, y, w, h, c) ;
}
}

CLASSE
Graphique

INTERFACE
Traçable

CLASSE CLASSE
Cercle Rectangle

CLASSE
RectangleTracable
 étend la classe
Rectangle
 implémente
l'interface
Tracable

Figure 4 : l’implémentation, palliatif de l’héritage multiple

2.1.1.9. Les paquetages Java


Nous avons signalé supra l’importance, dans la technologie orienté objet, de la richesse et de la
pertinence du classement des bibliothèques de classes facilitant la ré-utilisabilité.

Le langage Java est fourni avec un ensemble de classes hiérarchisées et organisées en paquetages.
Chaque paquetage est rangé dans un dossier de la mémoire de l’ordinateur. Le chemin d’accès à ce
dossier correspond au nom du paquetage. Ainsi, sur un environnement DOS, le paquetage
java.applet sera rangé dans le dossier (ou répertoire) accessible par le chemin relatif « java\applet ».
Il existe ainsi une standardisation de l’adressage des classes et programmes qui facilite la recherche
des composants logiciels Java, en particulier, sur des machines en réseau.

Les paquetages de la version Java 1.1 sont :

 java.applet : classes pour implémenter les « applets »,


 java.awt : classes pour les interfaces graphiques utilisateurs,
 java.awt.event : trois catégories de classes, les événements (clic de souris, frappe d’une
touche de clavier…), les objets en attente d’événements et les classes à adapter,
 java.awt.image : classes pour le traitement des images,
 java.awt.peer : classes pour la définition d’interfaces. Ces classes sont peu utilisées, car
la plupart des applications passent par les classes Component qui créent ces « peers »
quand cela est nécessaire,
 java.beans : le « grain Java » est un composant logiciel, il regroupe un ensemble de
classes et des ressources. Il est décrit par ses services et peut être invoqué grâce à son
interface,
 java.io : classes pour la gestion des entrées et sorties,
 java.lang : classes et types primitifs généraux du langage. La classe Object fait partie de
ce paquetage,
 java.lang.reflect : permet d’interroger une classe pour en connaître ses membres, utilisé
par les concepteurs de compilateur / dé-compilateur,
 java.math : pour l’utilisation de nombres flottants de très grande précision.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 17 / 49


 java.net : classes pour la gestion des échanges d’information en réseau (URL, Socket…),
 java.text : classes pour une utilisation internationale des formats (dates, message,
nombre),
 java.util : classes qui sont des utilitaires,
 java.util.zip : classes pour la compression et la dé-compression.

16. Le polymorphisme et la surcharge


2.1.1.10. Définition
Le polymorphisme décrit le comportement qui fait qu’un même message, envoyé vers des objets
différents a un résultat dépendant de la nature de l’objet recevant le message. Une méthode aura un
code différent selon l’objet vers lequel elle a été invoquée. La méthode est invoquée, dans tous les
cas, avec les mêmes nom, paramètres et type de retour.

Le polymorphisme implique une résolution ou liaison dynamique. Le code à appliquer est connu
de l’interpréteur seulement lorsqu’il sait sur quel objet la méthode est invoquée. La résolution a
lieu au moment de l’exécution du programme.

La surchage est la possibilité d’avoir le même nom de méthode mais avec des arguments
différents. Dans le cas d’une surcharge, la liaison est réalisée lors de la compilation.

2.1.1.11. Le polymorphisme et la surcharge en Java


Le langage Java autorise la redéfinition de méthodes. Quand une classe déclare une méthode avec
les mêmes nom, arguments et retour que sa super classe, on dit que la méthode est redéfinie. La
méthode, invoquée sur un objet de cette classe, provoquera l’exécution du code de la classe et non
celui de la super-classe. Un même message envoyé sur un objet de la super-classe et sur un objet de
la classe aura des résultats différents selon le type d’objet. C’est donc une forme de
polymorphisme.

Le compilateur Java ne peut pas établir le lien entre l’appel (le message) et la méthode à exécuter.
C’est seulement lors de l’exécution du programme que le run-time connaît l’objet et donc la
version la plus spécifique de la méthode à appliquer que la résolution peut avoir lieu. On parle de
résolution tardive ou de lien dynamique par opposition à la résolution précoce généralement
adoptée par les langages de programmation non orienté objet. La liaison dynamique peut être
implémentée efficacement, mais elle n’est pas aussi rapide qu’un appel direct. Il existe des cas pour
lesquels Java n’a pas besoin de liaison dynamique : les méthodes déclarées statiques et finales - ne
peuvent pas être redéfinies – celles déclarées privées – ne sont pas héritées par leurs sous-classes -
et celles des classes finales.

La surcharge est aussi possible en Java : on peut définir des méthodes de même nom ayant des
arguments différents.

Un exemple de surcharge :

int somme (int a, int b) {


return (a + b) ;
}
int somme (int a, int b, int c) {
return (a + b + c) ;
}
float somme (float a, float b) {
return (a + b) ;
}
int entA = 1, entB = 2, entC = 9 ;
float fA = 1.3, fB = 2.6 ;

CNAM – Examen probatoire – mai 1999 – le langage Java – page 18 / 49


int entSomme = somme (entA, entB, entC) ;
float fSomme = somme (fA, fB) ;

2.2. La construction d’un programme Java


Le programme Java est d’abord écrit avec un éditeur de texte et sauvegardé au format texte dans un
fichier dont le nom sera celui de la classe suivi de l’extension.java.

Un exemple traditionnel :

public class MessagedeBienvenue {


public static void main ( String [] args ) {
System.out.println ( « Bienvenue dans le monde de Java ») ;
}
}

Le programme est ensuite compilé avec le compilateur Javac du JDK 1.2, au moyen de
l’instruction :

 javac MessagedeBienvenue.java

Le compilateur crée un fichier MessagedeBienvenue.class. L’instruction qui suit permet


l’interprétation et l’exécution du programme.

 java MessagedeBienvenue

Le programme affiche :

 Bienvenue dans le monde de Java

2.3. La syntaxe de Java


La syntaxe Java est très proche de celle des langages C et C++. Nous présentons ci-après très
rapidement les principaux éléments de cette syntaxe.

17. Les types


2.3.1.1. Les types primitifs
Tout est objet en Java, sauf trois types primitifs : les types numériques, les booléens et les
caractères. La taille de chaque type est définie par le langage et est indépendante de
l’implémentation contrairement au langage C.

Type Contenu Valeur par défaut Taille


Boolean true ou false False 1 bit
Char caractère Unicode \u0000 16 bits
Byte entier signé 0 8 bits
Short entier signé 0 16 bits
Int entier signé 0 32 bits
Long entier signé 0 64 bits
Float flottant IEEE 754 0.0 32 bits
Double flottant IEEE 754 0.0 64 bits
Contrairement à C, Java a spécifié un type booléen comme type primitif.

2.3.1.2. Les tableaux


Les tableaux sont des objets à part entière. Ils peuvent être de tous types. On peut avoir des
tableaux de tableaux.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 19 / 49


Un exemple de tableau de points :

Point TableaudePoints [] ;


TableaudePoints = new Point [10] ;

Les tableaux sont indexés par des entiers. L’indexation commence à 0.

2.3.1.3. Les chaînes


Les chaînes sont des objets et non des tableaux de caractères comme en C.

Un exemple de chaîne de caractère :

String ChainedeCaractère = « Ceci est un exemple » ;

Il existe deux classes de chaînes : String pour les chaînes non modifiables après leur construction
et StringBuffer pour celles qui devront être modifiées.

Les opérations courantes que l’on peut mener sur une chaîne sont : créer, extraire, rechercher,
comparer, concaténer…

En Java, les caractères, les chaînes et les identificateurs sont composés de caractères 16-bits
Unicode. L’encodage Unicode code un caractère sur 16 bits. Il contient tous les alphabets et les
idéogrammes communément utilisés dans le monde. Les caractères ASCII et Latin 1 peuvent
facilement être transformés en caractères Unicode. C’est un atout de Java, avec lequel on peut
programmer avec, par exemple, des accents.

2.3.1.4. Les opérateurs


Les opérateurs (arithmétiques, de comparaison, de concaténation…) sont à peu de chose près les
mêmes que ceux de C ou de C++.

2.3.1.5. Les modificateurs


Les modificateurs de classes, de méthodes et de variables et ceux de visibilité sont rappelés ci-
après.

Modificateur S’applique à Signification

abstract classe, interface, méthode Classe abstraite non instanciée et non


implémentée. Méthode abstraite sans
corps.

final classe, variable, interface, Classe non extensible. Méthode non


méthode redéfinissable. Variable non modifiable.

native méthode Méthode implémentée dans un autre


langage, en général C.

none (package) classe, interface, variable, Classe, variable, méthode et interface


méthode accessibles seulement dans leur
paquetage et n’étant ni privée, ni
protégée, ni public.

private variable, méthode Seulement accessible dans la classe

protected variable, méthode Seulement accessible dans le paquetage


et les sous-classes.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 20 / 49


public classe, interface Accessible de partout

static classe, variable, méthode, Classe de niveau extérieur par


constructeur opposition à une classe interne.
Variable et méthode de classe. Le
constructeur est chargé à la création de
la classe.

synchronized méthode Réalise des modifications non


atomiques sur la classe ou l’instance. Il
est nécessaire de verrouiller la classe
(méthode statique) ou l’objet (méthode
non statique).

transient variable Ne fait pas partie de l’état persistant de


l’objet.

volatile variable Accessible par un processus non


synchronisé.

2.3.1.6. Les structures de contrôles


les structures de contrôles regroupent principalement, en C++ comme en Java : les branchements
conditionnels, les boucles et les sauts. Contrairement à C++, il n’y a pas de « GOTO ». Cependant,
deux instructions permettent de sortir d’une boucle et de revenir au début d’une boucle : « break »
et « continue ». La syntaxe est pratiquement identique à celle de C++.

Les branchements conditionnels

Exemple : if …then …else….


if (expression)
/* « expression » est un booléen et ne peut être un entier comme en C */
{
action () ;
}
else
{
autreAction () ;
}

Autre branchement : switch…


switch (valeurEntiere)
{
case (1) ; opération1 () ;
case (2) ; opération2 () ;
default ; opérationDefault () ;
}

Les boucles
La syntaxe est la même qu’en C ou C++.
while (expression)
{
action () ;
}
do
{
action () ;
}

CNAM – Examen probatoire – mai 1999 – le langage Java – page 21 / 49


for (int i = valeurDépart ; i <= valeurFinal ; i++)
{
action () ;
}

Les sauts

Il existe deux instructions : « break » pour sortir d’une boucle et « continue » pour revenir au début
de la boucle. On peut placer des labels sur les boucles ou constructions par « switch », et sortir au
moyen du « break » ou continuer par « continue » vers le bloc désigné par le label.

Exemple d’algorithme qui détermine si une chaîne de caractères est incluse dans une autre chaîne :
test: for (int i = fromIndex ; i + max1 <= max2; i++) {
if (charAt(i) == c0) {
for (int k = 1 ; k < max1 ; k++) {
if (charAt(i+k) != str.charAt(k)) {
continue test; /* sortir de la boucle interne et continuer à partir de
l’étiquette test */
}
} /* end of inner for loop */
}
} /* end of outer for loop */

2.4. Les « applets »


18. Qu’est-ce qu’une « applet » ?
Une « applet » ou appliquette est une petite application, écrite en Java, dont le code est téléchargé à
partir du serveur lors de l’affichage de la page HTML, et qui s’exécute sur le poste client au
moment de l’affichage de la page HTML. Alors qu’une application autonome (classique) s’exécute
directement sous le contrôle du système d’exploitation, une appliquette s’exécute sous le contrôle
du navigageur.

19. Pourquoi des « applets » ?


Elles permettent de transformer les pages HTML statiques pour obtenir des écrans animés et
réactifs.

Une autre technique existe : le langage JavaScrip permet l’ajout dans le code HTML de scripts. Le
code des scripts est interprété en totalité. L’avantage est la simplicité de la mise en œuvre et de
programmation, l’inconvénient se situe dans les limites fonctionnelles de ces scripts. Il n’est pas
possible, en effet, avec un script de réaliser une interactivité un peu complexe.

Les « applets » Java, utilisées pour rendre les pages interactives, transitent sur le réseau sous une
forme partiellement compilée : en bytecode. Une fois le code transféré sur le poste client, elles
s’exécutent grâce à la machine virtuelle Java (JVM) intégrée au Navigateur. L’utilisation des
« applets » présente des avantages : le code peut rester indépendant des plates-formes, il est moins
volumineux et son interprétation est plus rapide qu’un code source.

20. Comment programmer une « applet » ?


Pour afficher une appliquette, nous avons besoin d’en indiquer l’appel dans le fichier HTML de la
façon suivante :
<TITLE>Applet de gribouillage J.D. d’après Java in a Nutshell</TITLE>
<HEAD> </HEAD>
<BODY>
<APPLET code = Scribble3.class WIDTH = 300 HEIGHT = 200> </APPLET>
</BODY>

Il reste à écrire la classe « Sribble.class » en Java et à la compiler avec javac.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 22 / 49


L’Applet de gribouillage va illustrer ce qui est dit supra au sujet des événements. Elle permet
d’afficher à l’écran une zone où l’utilisateur pourra dessiner.
/* Applet de gribouillage inspiré de « Java in a Nutshell » - Java 2 */
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Scribble3 extends Applet {
private int lastx = 0 ;
private int lasty = 0 ;
public void init() {
/* définit, instancie et enregistre un objet MouseListener en attente
d’événements */
this.addMouseListener(new MouseAdapter()
{
public void mousePressed (MouseEvent e)
{
lastx = e.getX () ;
lasty = e.getY () ;
}
}) ;
//Définit, instancie et enregistre un objet MouseMotionListener
this.addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged (MouseEvent e)
{
Graphics g = getGraphics () ;
int x = e.getX (), y = e.getY () ;
g.setColor (Color.black) ;
g.drawLine (lastx, lasty, x, y) ;
lastx = x ;
lasty = y ;
} }) ;
//Créé un bouton " Effacer "
Button b = new Button ("Effacer") ;
//Définit, instancie et enregistre un bouton en écoute d'événement
b.addActionListener (new ActionListener ()
{
public void actionPerformed (ActionEvent e)//Efface l'écran
{
Graphics g = getGraphics () ;
g.setColor (getBackground()) ;
g.fillRect (0,0, getSize().width, getSize().height) ;
}
}
) ;
this.add (b) ; /* Ajouter le bouton */ }}

Figure 5 : une « applet » de gribouillage

CNAM – Examen probatoire – mai 1999 – le langage Java – page 23 / 49


21. La gestion des événements
La gestion des événements a été modifiée de façon importante depuis la version 1.1 de Java. Elle
implique l’ajout au composant d’un objet spécialisé dans l’écoute, un « listener » qui sera en attente
d’un événement. Cet objet doit appartenir à une classe qui implémente l’Interface EventListener
ou une Interface dérivée de celle-ci. Comme il est parfois plus facile d’étendre une classe que
d’implémenter une interface, Java a créé des classes spécifiques dont le nom se termine par
« Adapter », par exemple la classe MouseAdapter, qui sont des adaptations triviales des interfaces
dérivées de EventListener.

Ainsi, dans l’exemple Scribble3, on utilise deux classes locales anonymes (nous étudierons plus
loin les classes internes) qui étendent les classes MouseAdapter, MouseMotionAdapter et
ActionListener et permettent l’ajout d’un objet spécialisé dans l’écoute. Les méthodes héritées
mousePressed, mouseDragged et actionPerformed sont redéfinies. 

Les méthodes mousePressed et mouseDragged sont activées quand l’utilisateur clique sur le
bouton de la souris ou le maintient enfoncé en se déplaçant.

La méthode actionPerformed est invoquée quand l’utilisateur clique sur le bouton « Effacer ».
Elle remplit le cadre de la couleur de fond.

L’  « applet » hérite de la méthode paint() dont l’implémentation est vide. Le dessin est donc perdu
à chaque fois que l’  « applet » est redessinée : par exemple quand l’utilisateur fait passer une autre
fenêtre en avant plan.

22. La sécurité des « applets »


Si elles ne comportaient pas de restrictions, les « applets » chargées par le réseau pourraient servir
d’outils à des utilisateurs mal intentionnés pour dégrader les données ou le système. Par sécurité,
Java impose des limites à ce que peut faire une « applet ». En règle générale, les « applets » ne
peuvent pas :

 lire, écrire, détruire, renommer, obtenir des informations sur les dates de
modification des fichiers locaux,
 créer, lister, détruire des répertoires,
 charger des librairies ou des méthodes natives.
Ces limites peuvent être trop contraignantes dans le cas d’un Intranet ou d’un Extranet. Il est alors
possible, dans Java 2, de résoudre cette question en configurant le « security manager » à l’aide
d’un objet de la classe SecurityManager. Le manager de sécurité est installé par le navigateur qui
affiche l’ « applet ».

Des mécanismes de sécurité sont implantés pour le chargement des classes. Les classes de
chargement s’assurent que les classes chargées à partir du réseau et celles chargées à partir de la
machine locale sont dans des espaces de nom différents (éviter les conflits de noms et l’écrasement
d’une « applet » locale). Elles vérifient également que le code est un code de la JVM (Java Virtual
Machine), qu’il n’effectue pas de débordement de pile, qu’il n’utilise pas de registre incorrect et
n’effectue pas de conversion illégale de code.

L’utilisation abusive des ressources du système local lors de l’exécution d’une « applet »
( exécution de « threads » trop gourmands, transferts de données trop volumineuses) ne peut être
contrôlée. Heureusement, ce type d’attaque n’est pas réellement dangereux.

2.5. Les interfaces graphiques


23. Le paquetage java.awt
Le paquetage java.awt regroupent des classes et interfaces nécessaires à la programmation des
interfaces graphiques. Celles-ci se répartissent en trois sous ensembles :

CNAM – Examen probatoire – mai 1999 – le langage Java – page 24 / 49


 les éléments graphiques : couleurs, police de caractères, images, formes…
 les composants (voir hiérarchie figure 6) : définition des classes de la GUI (« Graphical
User Interface »), ils comprennent eux-mêmes :
 les conteneurs : fenêtres, cadres, panneaux…
 les boutons, les menus et les boîtes à contrôles (Checkbox),
 les canevas : zones pour dessiner,
 les gestionnaires de mise en page : ils contrôlent la taille et la position des composants
dans les conteneurs.

Canvas Component Choice

Button Checkbox

Container

Panel Window

Applet
Frame Dialog

Figure 6 : une partie de la hiérarchie des objets graphiques en Java

La classe abstraite Container sert de support à des éléments graphiques de deux types : les objets
de la classe Panel (groupes d’objets à l’intérieur de la fenêtre courante) et ceux de la classe
Window (fenêtres indépendantes). Celle-ci se spécialise en deux autres classes : la classe Frame
décrit les fenêtres principales et la classe Dialog affiche des objets fenêtres servant à l’affichage
simple de messages.

Les objets conteneurs utilisent un gestionnaire de mise en page de la classe « LayoutManager ». Il


dispose les objets dans le conteneur. En standard, la librairie propose plusieurs types de
dispositions : BorderLayout répartit les objets sur les bords de la fenêtre, FlowLayout le fait
horizontalement, GridLayout les dispose dans un tableau. CardLayout permet de gérer plusieurs
composants dont un seul est visible à la fois. GridBagLayout est conçu plus spécialement pour
gérer les situations « complexes ».

Avec le langage Java, un utilisateur peut choisir différents visuels d’interface : un semblable à celui
des PC sous Windows, un à celle d’un Macintosh ou un autre à une station Unix. Il peut également
créer son propre visuel. Tout ceci repose sur le fait que beaucoup d’éléments d’interface (boutons,
fenêtre, listes déroulantes…) sont écrits en Java et non empruntés au système.

Il existe des composants lourds et des composants légers.

Les composants lourds sont ceux dont l’implémentation dépend du système. On fait appel à une
fonction du système. L’inconvénient est que le programme devra avoir une version pour chaque
système : une version pour Macintosh, une pour PC, une pour station Sun … Il faudra donc
plusieurs programmes sources.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 25 / 49


En Java, quelques composants sont des composants lourds. Pour créer un composant lourd, Java
l’associe à un élément dépendant du système appelé peer. Le paquetage java.peer est prévu pour
établir cette relation.

Les composants légers sont des composants entièrement écrits en Java. Il en existe pour différents
visuels et chaque visuel peut fonctionner sur tous les systèmes. Les quatre visuels existants sont :
Windows, Macintosh, Motif (souvent utilisé sur stations UNIX) et Metal (créé pour Java).

Java propose des classes pour tous les éléments d’interface sous forme de composants lourds. Ils
font partie du paquetage java.awt.

24. Le paquetage javax.swing de la version 2 de java


A côte du paquetage java.awt, la version 2 de Java propose un paquetage dénommé javax.swing. Il
fait correspondre, à chacune des quatre classes du paquetage java.awt, une classe du paquetage
Swing portant le même nom précédé d’un J. Ces 4 classes sont les seules du paquetage swing à être
des composants lourds.

Window Applet
(lourd) (lourd)

java.awt
Frame Dialog
(lourd) (lourd)

JFrame JDialog JWindow JApplet JInternalFrame


(lourd) (lourd) (lourd) (lourd) (léger)

JRootPane javax.swing
(léger)

Figure 7 : hiérarchie des fenêtres en Java

Dans le paquetage Swing, il existe un cinquième type de fenêtre JInternalFrame qui est un
composant léger et dont les instances sont des fenêtres appartenant à d’autres fenêtres.

A quoi sert le paquetage Swing ? Il sert à définir des composants légers qui sont écrits entièrement
en Java et sont presque totalement indépendants des plates-formes.

Les programmes Java ont pour objectifs de fonctionner sur tous les systèmes existant et à venir (si
possible). Or, pour ce qui concerne l’affichage, ces systèmes diffèrent par la taille, la résolution, le
nombre de couleurs et les ressources. Parmi les ressources différentes, nous citerons les polices de
caractères, tous les programmes y ont recours. La taille et la résolution de l’écran sont des
problèmes cruciaux : par exemple, pour avoir la même taille sur deux écrans de 17 pouces l’un en
résolution 800 x 600 et l’autre en 1600 x 1200, une fenêtre devra avoir une définition deux fois
supérieures dans un des deux cas.

Le travail du LayoutManager consiste, donc, à indiquer, non pas la position précise (coordonnées)


des éléments, mais le type de disposition souhaitée.

Nous prendrons l’exemple de la classe GridBagLayout pour créer la fenêtre de la figure 8. Un objet
de cette classe fonctionne comme un tableau dont les cellules peuvent être fusionnées. Il ne

CNAM – Examen probatoire – mai 1999 – le langage Java – page 26 / 49


demande aucun paramètre. Les paramètres sont fournis par un objet de la classe
GridBagConstraints.

On aura, pour chaque composant, la séquence suivante :

 Création d’un objet GridBagLayout pour le conteneur,


 Création d’un objet GridBagConstraints pour le premier composant,
 Initialisation des paramètres du GridBagConstraints ,
 Ajout du composant.

Figure 8 : La boîte de dialogue OUI / NON

La structure à mettre en œuvre est la suivante : un conteneur qui est un tableau de deux lignes et
deux colonnes, une étiquette centrée sur deux colonnes fusionnées et deux boutons.

Voulez-vous quitter ?

OUI NON

Exemple d’une boîte de dialogue OUI/NON réalisée avec le paquetage Swing.

/* Inspiré de « Le développeur Java2 » */


import javax.swing.* ;
import java.awt.event.* ;
import java.awt.* ;

public class GridBag2 {

public static void main (String[ ] args) {


FenetrePrincipale maFenetre = new FenetrePrincipale ( « Ma fenêtre » ) ;
}
}
class FenetrePrincipale extends JFrame {
FenetrePrincipale (String s) {
super (s) ; // Appel au constructeur de la super classe
addWindowListener (new WindowAdapter () {
public void windowClosing ( WindowEvent e) {
System.exit (0) ;
}}) ;

getContentPane().setLayout (new GridBagLayout ()) ;


GridBagConstraints c = new GridBagConstraints () ;
JLabel L1 = new JLabel (« Voulez-vous quitter ? ») ;

CNAM – Examen probatoire – mai 1999 – le langage Java – page 27 / 49


c.weightx = 1 ; //Si la taille du tableau est agrandie en largeur
c.ipadx = 10 ; //ajout à la largeur du composant - gauche et droite
c.gridwidth = GridBagConstraints.REMAINDER ; //dernier composant de ligne
c.gridheight = 1 ; //Valeur de la hauteur
c.insets = new Insets (60, 100, 20, 100) ;//espace autour du composant
getContentPane () .add (L1, c) ; // on ajoute le composant
JButton B1 = new JButton (« Oui ») ; // on passe au second composant
c.gridwidth = 1 ;
c.gridheight = GridBagConstraints.REMAINDER ;
c.insets = new Insets (20, 0, 60, 0) ;
getContentPane () .add (B1, c) ;
JButton B2 = new JButton (« Non ») ;
c.insets = new Insets (20, 0, 60, 0) ;
getContentPane () .add (B2, c) ;
setSize (getLayout () . preferredLayoutSize (this)) ;
setVisible (true) ;
setResizable (false) ;
} }

2.6. Les Entrées-Sorties


25. Principes généraux
Tout programme a besoin d’échanges avec l’extérieur : lire les informations que l’utilisateur tape à
l’écran, lire un fichier, renvoyer un message à l’utilisateur… En Java, les supports de
communication sont représentés par des objets particuliers dénommés « streams » ce qui signifie
« flots ». Les streams peuvent être classés selon différents critères correspondant à des besoins
différents :

 les streams d’entrées et les streams de sortie,


 les streams de caractères (texte) et les streams de données binaires - Les
caractères pourraient parfaitement être considérés comme des données binaires.
Cependant, les particularités des chaînes de caractères justifient l’utilisation de
streams spécifiques - ,
 les streams à accès séquentiel et les streams à accès direct,
 les streams de traitements de données (conversions, compressions) et les streams
de communication,
 les streams avec tampon de données et ceux sans tampon de données (pour
optimiser).

26. Le paquetage java.io de Java


Pour répondre aux besoins de la communication avec l’extérieur, Java possède une importante
bibliothèque de classes regroupées dans le paquetage java.io.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 28 / 49


java.lang java.io
ByteArrayInputStream

Object
FileInputStream

InputStream
FilterInputStream

File
ObjectInputStream

FilenameFilter PipedInputStream

SequenceInputStream
FileDescriptor

RandomAccesFile ByteArrayOutputStream

FileOutputStream
OutputStream
FilterOuputStream

ObjectStreamClass
ObjectOuputStream

StreamTokenizer
PipedOuputStream

BufferedReader

CharArrayReader
Reader

FlterReader

InputStreamReader BufferedWriter

PipedReader CharArrayWriter

StringReader FlterWriter

OutpûtStreamWriter
Writer

PipedWriter
Serializable

PrintWriter

Externalizable
StringWriter

Classe Interface Etend (hiérarchie)


Implémente
Classe abstraite Classe finale

Figure 9 : une partie du paquetage java.io

Les streams de données binaires dérivent de deux classes abstraites : InputStream pour les
entrées et OutputStream pour les sorties. Chaque catégorie, entrée ou sortie, comporte elle-même
des streams de communication et des streams de traitement.

Les streams de caractères dérivent aussi de deux classes abstraites : Reader et Writer. On trouve
également, en entrée ou en sortie, des streams de traitement et des streams de communication.

Les flots à accès directs sont gérés par la classe RandomAccesFile.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 29 / 49


La classe File permet de représenter un nom de fichier ou un nom de répertoire d’une façon
indépendante du système. Elle fournit des méthodes pour lister les répertoires, tester les attributs,
renommer et supprimer les fichiers.

La classe StreamTokenizer réalise l’analyse lexicale d’un flot d’entrée donné et découpe les
entrées en unités lexicales.

La classe finale FileDescriptor est une représentation indépendante de la plate-forme, d’une


référence bas niveau sur un fichier ouvert.

Les classes PipedInputStream et PipedOutputSream peuvent être utilisées pour permettre à


deux processus légers différents d’échanger des données. En effet, lors de l’utilisation de « pipes »,
les données circulent à partir d’une source à travers un ou plusieurs filtres pour aboutir dans un
« puits ». Par exemple, la source sera un fichier, le filtre une opération de recherche et remplace et
le puits un autre fichier ou l’écran. La source, les filtres et le « puits » sont implémentés comme des
processus légers séparés reliés par des « pipes ». Ils s’exécutent indépendamment les uns des
autres, sont bloqués lorsque aucune donnée en entrée n’est disponible et continue la lecture sur le
« pipe » lorsque les données sont disponibles.

27. La sérialisation
Les classes ObjectStreamClass, ObjectInputStream, ObjectOutputStream, l’interface
Serializable vont permettre de lire et d’enregistrer dans un flot (sur disque par exemple) des objets.
Cette opération est appelée sérialisation. Elle permet de conserver les objets dans leur état entre
l’exécution des programmes. De cette façon que le langage Java gère la persistance des objets.
Dans une classe qui implémente l’interface Serializable, les attributs déclarés « transcient » ne
doivent pas être enregistrés ;

28. Un exemple : lecture et écriture d’un fichier


Ce programme doit être lancé avec deux paramètres en entrée : le fichier source et le fichier
destination. Il effectue la copie du fichier source dans le fichier de destination. Il fonctionne bien,
mais il est très imparfait. Il vérifie si le fichier source existe et envoie un message d’erreur s’il
n’existe pas. Mais, par exemple, il ne vérifie pas si le fichier destination existe déjà et va donc
l’écraser sans prévenir. La gestion des exceptions et des erreurs sera traitée juste après.
import java.io.* ;
public class CopieTexte {

/* Le programme principal invoque une méthode qui va copier le fichier source


vers le fichier destination.*/

public static void main (String [] args) {


if (args.length != 2)
System.err.println
( " Vous devez donner le nom des fichiers source et destination ") ;
else {
/* gestion des erreurs : si le fichier n’existe pas, un message système est
affiché */
try { copie (args[0], args [1]) ;}
catch (IOException e) {System.err.println ( e.getMessage () ) ; }
}
}
static int c ;

/* la méthode copie utilise throws pour signaler que les erreurs doivent être
gérées par les supers classes. */
public static void copie (String source, String destination) throws
IOException
{
FileReader flot1 = new FileReader (source)  ;

CNAM – Examen probatoire – mai 1999 – le langage Java – page 30 / 49


FileWriter flot2 = new FileWriter (destination) ;
/* La méthode read (de la super classe) lit le fichier octet par octet en
convertissant ce dernier en entier. La méthode write écrit en caractère dans
le fichier*/
while (( c = flot1.read ()) != -1)
flot2.write ( c ) ;
flot1.close() ;
flot2.close () ;
}
}

2.7. La gestion des exceptions


29. Qu’appelle-t-on exceptions ?
Les exceptions désignent les conditions inattendues qui empêchent le programme de se dérouler
correctement. Dans l’exemple de programme ci-dessus qui effectuait une copie de fichier, une
exception traite le cas où le programme est appelé sans les deux arguments qui sont indispensables
à son fonctionnement. Une autre exception, dont le traitement est laissé à l’interpréteur, concerne le
lancement du programme avec un nom de fichier source qui n’existe pas dans le répertoire.

Lorsqu’une exception se produit lors de l’exécution d’un programme, soit :

1. Elle était ou pouvait être prévue par le programmeur. Elle doit alors être traitée dans le
programme. Dans l’exemple de la copie de fichier, le programme doit prévoir le cas où
l’utilisateur va entrer un nom de fichier inexistant. Il doit lui signaler l’erreur et lui
demander un nouveau nom de fichier. Le programme n’est pas interrompu.

2. L’erreur était imprévisible. Dans ce cas, il s’agit d’une erreur qui dépend des conditions
d’exécution (classe non trouvée, machine virtuelle ans un état instable…).

Le langage Java classe les erreurs en deux catégories : les erreurs surveillées ou exceptions (cas 1)
(celles qui peuvent être prévues) et les erreurs non surveillées ou erreurs (cas 2) considérées
comme trop graves et ne pouvant être prévues à priori.

Il impose au programmeur de traiter à minima les erreurs surveillées ou exceptions. Le compilateur


ne laissera pas passer une méthode susceptible de lever une exception si celle-ci n’est pas capturée
ou, au moins, si la signature de cette méthode n’indique pas le type d’exception qu’elle laisse
passer. Une méthode peut capturer une exception et ne prévoir aucune correction, le traitement sera
alors interrompu lors de l’exécution et l’erreur signalée.

Le traitement des erreurs ou des exceptions dans les programmes est souvent négligé. Java oblige
les programmeurs à prendre en compte la gestion des erreurs et facilite leur tâche. Il a adopté deux
principes fondamentaux dans la gestion des erreurs. En premier lieu, le compilateur doit détecter la
plus grande partie des erreurs de façon à limiter celles qui interviendront durant le déroulement du
programme. En second, le traitement des erreurs doit être regroupé et séparé du reste du code de
façon à conserver la lisibilité de celui-ci. Le fonctionnement normal du programme apparaît ainsi à
première vue.

30. Les objets exceptions et la gestion des exceptions en Java


Une exception en Java est un objet, instance d’une sous classe de la classe java.lang.Throwable
qui se trouve au sommet de la hiérarchie. La classe Throwable comporte deux sous classes
standard : Error et Exception.

Les objets de la classe Error correspondent à des problèmes liés à l’édition des liens lors du
chargement dynamique de classes ou à la machine comme le manque de mémoire. Elles sont, en
général, considérées comme irrécupérables et ne sont pas capturées par le programme. Celles de la
classe Exception doivent être signalées et traitées.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 31 / 49


Le traitement peut se faire de deux façons :

 attraper l’exception et la traiter,


 indiquer dans la signature de la méthode ( clause throws) qu’elle est susceptible
de déclencher une exception. Les exceptions peuvent ainsi se propager en
remontant les structures lexicales des méthodes, puis la pile d’appel des
méthodes. Un bloc de code qui ne capture pas l’exception est dit négligeant. Si
aucun bloc de la méthode ne la capture ont dit que l’exception est triste et elle se
propage de méthode en méthode jusqu’au programme principal (main). Elle est
alors traitée par l’interpréteur Java.
2.7.1.1. Attraper l’exception et la traiter
Les instructions de gestion des exceptions sont : try / catch / finally.

try {} : délimite le bloc de code susceptible de générer une exception.

catch ( TypeException e){} : suit le bloc try. Il gère l’objet exception e. Il hérite de la classe
Throwable d’un objet de type String qui est le message d’erreur. La méthode get.Message () permet
de récupérer le message d’erreur associé à l’objet exception.

finally {} : ce code est exécuté systématiquement en sortant de la clase try, indépendamment de la
façon dont on l’a quittée. Il permet, par exemple, de fermer les fichiers.

2.7.1.2. Indiquer que la méthode est susceptible de générer une exception


La clause throws est utilisée comme suit :
public static void copie (String s, String d) throws IOException {}

Elle signifie que la méthode copie est susceptible de générer une exception, objet de la classe
java.lang.Exception.IOException, que cette exception n’est pas gérée par cette méthode. Les
méthodes utilisatrices de copie devront donc se poser la question de la gestion de l’exception.

31. Un exemple de gestion d’exceptions


Le programme ci-dessous effectue le calcul de la vitesse en km / heure à partir de la distance (en
km) et du temps (en heures) saisis au clavier par l’utilisateur. Ses méthodes traitent les erreurs
prévisibles. Les blocs et les méthodes ne sont pas négligents : ils ne laissent pas les erreurs à traiter
aux méthodes qui les utilisent. Il n’y a donc pas d’instruction throws qui signalerait les erreurs pour
l’extérieur.

Par contre, sa conception est très imparfaite : il ne prend que des valeurs entières et n’accepte pas
une distance parcourue de 0.
/* Programme de calcul (approximatif) de vitesse */

import java.io.* ;

public class GestionErreur {

public static void main ( String [] args ) {


int d = 0 ;
int t = 0 ;
int vitesse = 0 ;
System.out.println () ;
d = demander ( « Distance parcourue en km » ) ;
System.out.println () ;
t = demander ( « Temps en heures ») ;
vitesse = calculeVitesse (d, t) ;
System.out.println () ;

CNAM – Examen probatoire – mai 1999 – le langage Java – page 32 / 49


System.out.println (« La vitesse est de : » + vitesse + « km/heure. ») ;
}

public static int demander (String s) {


int n = 0 ;
int i = 0 ;
System.out.print ( s ) ;
BufferedReader tampon = new BufferedReader (new InputStreamReader
(System.in)) ;
// on n’accepte uniquement la saisie de nombres entiers > 0 et 3 essais.
while (n <= 0 && i < 3) {
System.out.print
(« (Saisissez un entier égal ou supérieur à 1) : ») ;
System.out.println () ;
try {n = (new Integer (tampon.readLine())) . intValue() ; }
catch (NumberFormatException e) {}
catch (IOException e) {
System.out.println (« Erreur de lecture ») ;
System.exit (0) ;
}
i++ ;
}
// Si l’utilisateur se trompe 3 fois, le prog. s’interrompt.
if (i == 3 && n <= 0){
System.out.println () ;
System.out.println (« Trop d’erreurs : au revoir… ») ;
System.exit (0) ;
}
return n ;
}

static int calculeVitesse (int d, int t) {


return d / t ;
}
}

2.8. La gestion des processus multiples légers « threads » (activités)


32. Qu’est-ce que les « threads » et à quoi servent-ils ?
Lorsque nous exécutons un programme, nous lançons un processus. C’est le cas des petits
programmes que nous avons lancés jusqu’à maintenant. Cependant, la plupart des programmes sont
capables d’exécuter plusieurs séquences d’instructions encore appelées « threads » ou activités (ce
qui signifie fil en anglais). Un « thread » est donc une suite d’instructions à l’intérieur d’un
programme. Les programmes qui utilisent plusieurs « threads » sont dits « multithreadés ».

Les systèmes d’exploitation sont, en général multitâche, c’est à dire qu’ils sont capables de gérer
plusieurs processus en partageant le temps entre chacun (il ne s’agit pas de traitements qui
s’exécutent de façon parallèle). Mais, il arrive fréquemment que le programmeur souhaite lancer
des activités simultanément et qu’il ait besoin de contrôler leur mode de synchronisation afin de ne
pas être dépendant de la synchronisation réalisée par le système.

Si nous prenons l’exemple d’un programme de gestion de voyages. Il est indispensable qu’il puisse
être accédé par des utilisateurs différents en même temps. Chaque utilisateur va créer son propre
« thread ». Plusieurs utilisateurs peuvent essayer de s’inscrire en même temps à un même voyage
dont les places sont limitées. Le programmeur devra prévoir ce genre de cas et verrouiller un bloc
d’instructions afin, par exemple, que l’exécution du bloc ne puisse être interrompue par une autre
activité.

33. Les activités multiples (« threads ») dans le langage Java


En Java, les « threads » sont des objets, instances de la classe java.lang.Thread qui dérive
directement de la classe java.lang.Object.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 33 / 49


Il existe deux façons de créer des objets « threads » en Java :

 créer une sous classe de la classe Thread et l’instancier,


 créer une classe qui implémente l’interface spéciale Runnable et l’instancier.
Cette deuxième façon de faire est utilisée, rappelons que l’héritage multiple
n’est pas possible, quand la classe que l’on veut créer pour instancier les
activités dérive déjà d’une autre classe.
Ci-dessous, nous définissons la classe monActivite qui dérive de Thread et la méthode run ( ) qui
spécifie les instructions et nous lançons l’exécution de deux « threads » simultanés.
public class MonActivite extends Thread {
static int j = 1 ;
public void run () {
for (int i = 1 ; i <= 20 ; i++)
System.out.println ( j++ + «  » +  getName ()  ) ;
}
public static void main (String [] args) {
Thread t0 = new MonActivite () ;
Thread t1 = new MonActivite () ;
t0.start () ;
t1.start () ;
}
}

Pour exécuter plusieurs « threads » simultanément, il suffit de créer plusieurs instances de la classe
dérivée de Thread et d’invoquer plusieurs fois la méthode start (). L’exécution du programme
donne un résultat qui varie selon les machines. Rien ne nous permet de dire que l’activité 0 va
afficher les nombres impairs et l’activité 1 les nombres pairs.
1 Thread-0
2 Thread-1
3 Thread-0
4 Thread-1
5 Thread-1
6 Thread-0

40 Thread-0

Pour contrôler les activités, il existe plusieurs méthodes : yield () laisse passer du temps pour
l’exécution des autres activités, sleep () et interrupt() interrompent le déroulement d’une activité,
join () attend la fin de l’exécution.

Les méthodes setPriority (MAX_PRIORITY) et setPriority (MIN_PRIORITY) sont une façon


de gérer la répartition du temps entre les activités en gérant les priorités.

Lorsque deux activités doivent accéder à un même objet, il est parfois nécessaire de pouvoir
verrouiller cet objet. Ce principe est mis en œuvre dans les systèmes de gestion de base de
données. La première séquence d’instructions doit avoir un moyen de bloquer les modifications sur
l’objet durant l’exécution de ses instructions.

34. La synchronisation
Java propose le mot clé synchronized qui peut être appliqué à un bloc d’instructions pour signaler
une section critique de code. Le même mot clé peut aussi être utilisé comme modificateur pour une
une méthode d’instance. Quand une méthode englobée par une instruction de synchronisation est
exécutée, elle acquière un moniteur pour l'objet courant. Le moniteur exclut toute autre méthode
synchronisée appliquée à cet objet lors de l'exécution. Quand une méthode synchronisée se termine
de n'importe quelle façon, le moniteur est libéré. Les autres méthodes synchronisées de l'objet
peuvent être désormais exécutées.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 34 / 49


Pour obtenir des objets sans risque lors des exécutions d’activités multiples, toutes les méthodes
susceptibles de changer les valeurs des variables d'instance doivent être déclarées « synchronized ».
Cela implique qu'une seule méthode peut changer l'état d'un objet à un instant précis. Les moniteurs
Java sont ré-entrants : une méthode peut acquérir le même moniteur plus d'une fois. Le mécanisme
d'exclusion mutuelle présent dans Java est donc le moniteur

35. La communication entre activités


Pour synchroniser des activités qui accèdent aux mêmes ressources, on a vu que l'utilisation des
moniteurs permet de garantir l'exclusion mutuelle, la communication entre les activités utilise des
signaux, qui sont modélisés par les méthodes wait() et notify(). L’une met l’activité en attente,
l’autre la réveille.

Il existe deux variantes de la méthode wait () qui permettent de spécifier un temps limite après
lequel le processus sera réveillé, sans avoir à être notifié par un processus concurrent. Il n'est pas
possible de savoir si wait () s'est terminée à cause d'un appel à notify () par un autre processus ou à
cause de l'épuisement du temps.

La méthode notifyAll () réveille tous les processus. Plus précisément, Ils se réveilleront tour à tour
au fur et à mesure de la libération des moniteurs. Les méthodes wait, notify() et notifyAll() ne
peuvent être appelées que dans des méthodes synchronisées.

yie ld ()

new Thread ()

New Thread start () Runnable wait () Not Runnable


notify ()

stop ()
stop () or run () exits

Dead

Figure 10 : les états d'un « thread »

Comme exemple d’utilisation de communication entre des activités, on peut citer l’exemple
d’activités producteurs-consommateurs avec un tampon borné de n objets, un processus producteur
et un processus consommateur. On déclare les 2 processus, un producteur et un consommateur. On
doit faire en sorte que les données soient produites plus vite que le consommateur ne peut les
prélever, à cause de la différence de durée des délais (aléatoires) introduits dans les 2 processus.

Un exemple de « thread » de type démon est celui du "garbage collector" qui tourne en permanence
à la recherche d'objets non-référencés pour libérer de la mémoire.

36. Groupes de « thread »


La classe ThreadGroup définit des groupes de « threads » et permet des opérations sur l’ensemble
des « threads » du groupe. Les objets ThreadGroup peuvent contenir des objets Threads ou des
objets ThreadGroup « fils ». Tous les objets ThreadGroup sont crées comme « fils » d’un autre
objet ThreadGroup. L’utilisation des groupes de « thread » facilite la communication entre eux et
leur référencement.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 35 / 49


ThreadGroup monThreadGroup = new ThreadGroup("Mon groupe d’activité");
Thread myThread = new Thread(myThreadGroup, "une activité de mon groupe");

Pour trouver le groupe d'appartenance d'un « thread » :


theGroup = myThread.getThreadGroup();

2.9. La communication réseau


37. A quoi set la communication réseau ?
La communication réseau sert à programmer l’accès à des serveurs distants par le biais d’URL
(Uniform Ressource Locator) et à échanger des données avec différents protocoles  : TCP/IP
(Transfert Communication Protocole/ Internet Protocole : mode connecté) ou (Unreliable
Datagramme Standard Protocole : standard Internet mode non connecté). Elle est nécessaire dans la
programmation des applications clients/serveurs.

38. Le paquetage java.net


La classe URL instancie des objets qui sont des adresses Internet. La classe URLConnection
fournit des méthodes supplémentaires permettant, par exemple, de récupérer le contenu de la page
HTML référencée par l’URL.

La classe Socket permet, côté client, de se connecter à un port donné d’un hôte donné Internet et de
lire et d’écrire des données grâce aux classes InputStream et OutputStream du paquetage java.io.
Dans le cas de l’implémentation d’un serveur, pour accepter les demandes de connexions d’un
client, on utilisera la classe ServeurSocket. Ces deux classes utilisent la classe d’adresse
InetAdresse (adresse Internet).

Enfin, les objets du DatagramPacket sont réceptionnés et envoyés par ceux de la classe
DatagrammeSocket. Ils sont utilisés pour la programmation de bas niveau.

2.10. Les évolutions récentes de Java


Nous avons choisi de regrouper sous un titre spécifique les évolutions récentes de Java pour des
raisons de commodités mais, également parce que cela permet de mettre en évidence le sens de ces
évolutions. Nous ne reviendrons pas sur les classes du paquetage « swing » (apport de la version
1.2 de Java) ni sur la sérialisation qui font partie des évolutions récentes, mais qui ont été abordées
supra.

39. Les classes internes ou « Inner class »


Certaines classes sont parfois utilisées par une seule classe. Java autorise, depuis sa version 1.1, la
déclaration de classes à l’intérieur d’une autre classe. Quatre nouveaux types de classes ont ainsi
été définis : les classes imbriquées, les classes membres, les classes locales et les classes anonymes.
Ces nouvelles définitions permettent de mieux structurer les programmes et de les rendre plus
lisibles.

2.10.1.1. Les classes imbriquées


Les classes imbriquées sont des classes qui ne sont utilisées que par d’autres classes. Elles sont
déclarées à l’intérieur de celles-ci, toujours avec le modificateur « static ». Elles ne sont pas
destinées à être instanciées et ne peuvent avoir que des variables statiques.

2.10.1.2. Les classes membres


Les classes membres sont, elles aussi, déclarées à l’intérieur d’autres classes. Mais, elles ne sont
pas statiques. Quand une classe qui comporte des classes membres est instanciée, chacune de ces
classes membres est également instanciée. Les classes membres ne peuvent pas définir de membres
statiques.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 36 / 49


2.10.1.3. Les classes locales
Les classes locales sont définies à l’intérieur d’un bloc et ne sont visibles qu’à l’intérieur de ce
bloc. Les classes locales, tout comme les classes membres, ne peuvent pas définir de membres
statiques. A la compilation, un fichier « NomdeClasse$NomdeClasseLocale.class » est créé.

2.10.1.4. Les classes anonymes


Ce sont des cas particuliers de classes locales : elles sont définies sans nom comme suit :
new Nom_de_classe ( liste d’arguments ) { définition }

40. Les JavaBeans


Une des évolutions importantes de la version 1.1 du langage Java est la création des JavaBeans. Ils
sont à la base de différentes extensions du langage : la bibliothèque de composants graphiques
portables (les JFC – Java Foundation Class) et les Enterprises Java Beans (EJB). Ceux-ci sont des
composants logiciels développés par Sun. Ils sont utilisés par des serveurs d’applications pour
accéder aux données, s’interfacer avec des moniteurs transactionnels, prendre en charge
l’administration ou encapsuler des règles et des fonctions métiers..

2.10.1.5. Qu’est-ce qu’un JavaBean ?


Un JavaBean est un composant logiciel. Il permet une encapsulation plus poussée que les classes.
Ce qui diminue le nombre de composants logiciels et la complexité de leur utilisation.

Un JavaBean répond à plusieurs caractéristiques :

1. Il possède des fonctionnalités bien identifiées : un comportement, des données et des


événements. Un bouton, par exemple, aura un comportement (possibilité de changer de
taille, d’avoir le focus), des données (un libellé, une couleur..) et émet un événement
lorsque l’utilisateur clique dessus. Ces fonctionnalités peuvent être plus ou moins
complexes, elles sont décrites lors de la phase de conception du système. Une méthode
comme UML (Unified Modeling Language) possède des outils qui aident à la mise en
évidence des composants et à leur définition.

2. Il a une interface d’utilisation simple et facilement compréhensible reposant sur des


conventions connues des utilisateurs. Cette interface est définie pour deux types
d’utilisateurs : l’environnement de développement et le développeur. Elle a deux
objectifs : permettre aux utilisateurs de découvrir rapidement les services qu’elle rend et
faciliter l’exploitation du JavaBean.

3. Son utilisation est possible par « programmation visuelle ».

2.10.1.6. A quoi servent les JavaBeans ?


Les JavaBeans ont trois catégories d’utilisation : le développement d’applications (par exemple une
interface graphique) en utilisant les composants logiciels fournis avec le langage Java,
l’implémentation de nouveaux Beans et le développement d’applications ré-utilisant des Beans
« maison » réalisés dans l’entreprise.

2.10.1.7. Le développement d’interfaces graphiques avec les JavaBeans


Pour développer une interface graphique interactive en utilisant les JavaBeans, il faut d’abord
choisir un environnement de développement, par exemple celui fourni par Sun, le BDK (Beans
Developpement Kit) qui a les caractéristiques minimales d’un environnement de développement
supportant les JavaBeans.

Les différentes étapes du développement de l’application de cette interface graphique seront :

CNAM – Examen probatoire – mai 1999 – le langage Java – page 37 / 49


 l’insertion des JavaBeans nécessaires pour l’application. Ils sont empaquetés dans des
fichiers au format JAR (Java Archives),
 l’analyse et l’intégration des fichiers d’archives à l’environnement par le BDK,
 la création des objets : l’instanciation des classes choisies se fait par glissement dans
l’éditeur graphique prévu,
 le paramétrage des Beans, c’est à dire la saisie de leurs propriétés,
 l’assemblage de Beans c’est à dire la définition de leurs interactions. Il faut assembler
les bons événements avec les bonnes méthodes,
 une fois les différents Beans paramétrés et assemblés, l’environnement doit permettre la
construction d’une application ou d’une appliquette.
Toutes ces étapes se font par programmation visuelle. Cependant, il ne faut pas se tromper, cette
programmation nécessite une bonne connaissance du langage Java, des mécanismes internes des
JavaBeans et des concepts qu’ils utilisent.

2.10.1.8. La construction de Beans


Quatre types de classes vont constituer un Bean :

 la classe d’implémentation constituant le cœur du Bean,


 des classes assurant la gestion des événements,
 la classe de description décrivant les caractéristiques du Bean,
 des classes permettant le paramétrage des composants.
La classe d’implémentation est à priori une classe normale, par exemple, une zone de saisie avec
incrémentation. Trois conditions en feront un Bean. La première est qu’elle soit sérialisable. Pour
cela, on ajoute une implémentation de l’interface Serializable. La deuxième est qu’elle ait un
constructeur par défaut (sans paramètre). La troisième est son empaquetage : il faut d’ajouter une
première instruction « package nomduPaquetage ».

2.10.1.9. La gestion dynamique des objets : introspection ou la réflexion (reflection)


Un concepteur d’applications peut connaître l’interface d’une classe en consultant la
documentation. En revanche, un programme, tel un environnement ou un compilateur, qui doit
utiliser dynamiquement un composant Java, ne peut utiliser la même documentation. Le langage
Java doit donc être capable de reconnaître ses propres caractéristiques. Il propose des objets qui
permettent d’interroger directement un composant pour en obtenir des informations sur sa
structure.

La méthode getClass (), définie dans la classe Object, renvoie une instance de Class qui permet de
décrire une classe (nom, classe mère, liste de ses méthodes, de ses variables de classe et
éventuellement de ses constructeurs et de ses variables d’instance).

La méthode getMethods (), définie dans la classe Class, retourne un tableau contenant les
spécifications de toutes les méthodes publiques de la classe à laquelle appartient l’objet et celles
héritées de ses supers classes.

2.10.1.10. Comment empaqueter un Bean ?


En s’appuyant sur ces outils, un environnement de développement est capable d’analyser la classe
d’implémentation d’un Bean. Il exploite pour cela la classe java.beans.Introspector qui détermine
de façon précise l’interface du JavaBean. Ce procédé présente cependant des inconvénients : toute
l’information devient souvent difficilement lisible.

Java fournit un moyen plus fin pour définir l’interface : l’interface BeanInfo. Elle s’appuie sur des
classes qui héritent toutes d’une même classe : java.beans.FeatureDescriptor. Ces classes
décrivent :

CNAM – Examen probatoire – mai 1999 – le langage Java – page 38 / 49


 le Bean : BeanDescriptor,
 les propriétés du Bean : PropertyDessriptor,
 les événements du Bean : EventSetDessriptor,
 les méthodes du Bean : MethodDescriptor.
Au final, un Bean est composé de plusieurs fichiers. Pour fonctionner correctement tous ces
fichiers sont nécessaires. L’empaquetage grâce au fichier d’archive.JAR ( Java Archives) permet de
rassembler tous les fichiers d’un Bean en un seul et de les compresser. le JDK (Java
Développement Kit) contient un fichier Jar.exe qui permet de créer des fichiers.JAR.

41. La librairie JDBC et les architectures client/serveur


La librairie JDBC (Java Data Base Connectivity) est une librairie de classes pour l’accès aux
systèmes de gestion de bases de données (SGBD). Ses classes et interfaces sont toutes définies
dans le paquetage java.sql.

La librairie JDBC permet de fonctionner avec des architectures client/serveur.

Java offre des facilités pour développer les programmes clients. Ces derniers, ne communiquent
pas directement avec le moteur du SGBD, mais d’abord avec l’interface client du SGBD qui gère
les protocoles de communication, en général spécifiques au SGBD.

Pour ce qui concerne le programme Java serveur, il est constitué de deux couches. La première est
orientée vers l’application Java. Elle communique avec l’application cliente Java. La deuxième
couche est orientée vers les serveurs SGBD. Elle nécessite des « drivers » JDBC qui sont
spécifiques aux SGBD. Il existe quatre types de drivers JDBC. Le premier, JDBC – ODBC bridge
est utilisé pour les SGBD définis par Microsoft. Le deuxième type est un driver manager JDBC
dédié à un SGBD particulier. Le troisième est une interface entre le driver manager JDBC et un
service d’accès aux données de type middleware. Le quatrième est une interface entre le driver
manager JDBC et l’interface serveur du SGBD, il encapsule complètement l’interface cliente du
SGBD.

Les objets de la librairie JDBC offrent les services d’ouverture de connexion avec le SGBD après
avoir chargé le driver JDBC ad hoc et d’encapsulation de tous types d’ordres, procédures et
requêtes SQL.

La librairie JDBC offre également des services de gestion des transactions SQL, de gestion des
avertissements et des erreurs SQL, de conversions de types SQL en objet Java, de gestions de
données volumineuses et d’accès dynamiques.

42. L’internationalisation
L’internationalisation est la recherche d’une souplesse suffisamment importante pour qu’un
programme puisse fonctionner partout dans le monde et s’adapte donc aux conditions locales.

Parmi les contextes locaux à prendre en compte, il y a la langue et les caractères qu’elle utilise. Le
code Unicode adopté par Java permet de représenter la plupart des caractères utilisés dans le monde
entier.

Le deuxième type de caractéristiques locales concerne les conventions de formatage des dates et du
temps. Le paquetage java.text propose des outils pour résoudre ce problème.

La troisième tâche d’internationalisation est de masquer à l’utilisateur tous les messages ou libellés
du langage qui sont en langue anglaise. Pour cela, la seule solution est de localiser tous les
messages à l’exécution du programme et de les traduire dans la langue du pays où l’application est
diffusée (en plusieurs langues si besoin). Java propose une classe RessourceBundle du paquetage
java.util. Elle permet de définir un paquet de ressources pour chaque contexte local.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 39 / 49


43. En conclusion
On peut dire que le langage Java lui-même est relativement stable. Les évolutions concernent
davantage les bibliothèques, avec le développement des composants logiciels (beans). Les
évolutions vont dans le sens d’une augmentation de la standardisation, d’une plus grande souplesse
grâce aux classes internes et d’un recourt plus important à la ré-utilisabilité.

2.11. Les environnements de développement Java


Les environnements de développement Java s’appuient tous sur les mêmes outils de base : la Java
Virtual Machine, les librairies de classes Java et le compilateur. La figure 11 présente les
différentes briques pouvant composer un environnement.

ASSISTANTS
Assistants bases de Assistants
Assistants
données relationnelles applications /
middleware
(architectures deux applets / Java
RMI/C ORBA/EJB
niveaux) Beans

SUPPORT
JAVA
Palette de Assemblage
Import/Export Support des
BEANS composants visuel de
Java Beans JFC / Swing
prédéfinis composants

Editeur de code Aide en ligne sur Interface avec ou


intelligent l'outil et sur l'API intégration d'un
Vues sur les Java serveur applicatif
Interfaces
composants du CORBA et/ou EJB
avec outils Gestionnaire de
projet : classes,
conception documentation
méthodes, Débogueur
UML
fichiers .... symbolique
Générateur d'interface multithread et à
graphique distance Outil d'aide au
Interfaces déploiement d'un
avec logiciel
gestionnaire Référentiel multi-projet, multidéveloppeur, multilangue
configuration
et versions
Support Support clients
JDK Compilateur
internationalisation HTML et Java

Figure 11 : les différentes briques d'un environnement de développement Java (d'après Informatiques magazine)

Un logiciel développé avec un environnement, pourra être repris intégralement dans un autre. Il est
donc possible, au sein d’une même entreprise lançant plusieurs projets de types différents, d’utiliser
des environnements différents. Un outil simple, autonome et facile d’apprentissage pour les
« applets » et un environnement plus complexe et puissant pour un projet d’envergure.

3. Les avantages et les inconvénients du langage Java

3.1. Eléments de comparaison avec C++


44. Performances
Java, en byte-code interprété par une machine virtuelle, est environ vingt fois plus lent que le même
programme écrit en C++. Mais, Java pourrait être compilé. Il existe trois solutions : les
compilateurs natifs, les compilateurs de byte-code et les compilateurs « just in time » (JIT).

3.1.1.1. Les compilateurs natifs


Ils traduisent directement le code source Java en un code exécutable par une machine donnée. Le
programme dans sa forme exécutable n’est plus portable. Le code source le reste (en théorie). Cette
solution pourrait convenir pour les plates-formes les plus répandues.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 40 / 49


3.1.1.2. Les compilateurs de byte-code
Ils traduisent le byte-code Java en un code exécutable par une machine donnée. La portabilité est
ainsi préservée jusqu’au byte-code. Ce type de solution semble très rare.

3.1.1.3. Les compilateurs JIT (Just In Time)


Ils traduisent le byte-code en code exécutable. Ils fonctionnent sur la machine de l’utilisateur. Ils
compilent le byte-code « à la volée », juste au moment où l’exécution du programme est demandée.
Par rapport à l’interprétation, on gagne du temps durant l’exécution, mais on en perd juste avant
pendant le temps de la compilation. C’est pourquoi, le plus souvent, l’utilisateur choisit s’il
souhaite l’interprétation ou la compilation. Le gain dépend, en effet, du déroulement des séquences
interactives du programme.

45. Les types primitifs


La définition des types primitifs est indépendante des machines. Les vérifications de types sont
plus strictes en Java, ainsi une expression conditionnelle est strictement booléenne et ne peut être
numérique (comme en C++).

Le type Char de Java utilise la convention internationale UNICODE 16 bits et non l’ASCII comme
C++. Il n’existe pas de tableau de caractères somme en C++.

46. Les objets et classes


Contrairement à C++, en Java tout est objet, sauf les types primitifs incluant les booléens.

Il n’y a pas de variable ou de fonction globale. On peut avoir l’équivalent en déclarant des variables
ou des méthodes statiques à l’intérieur d’une classe.

Toutes les descriptions de méthodes sont définies dans le corps des classes. Java peut donc utiliser
le « . » pour toute appellation de méthodes ou variable. En complément, les noms de paquetage
utilisent aussi le « . ».

Toutes les créations d’objets se font par l’instruction « new ». Il n’y a pas de déclaration implicite
comme en C++. Tous les objets sont initialisés à « NUL » s’il n’y a pas de déclaration explicite.

47. Les tableaux, vecteurs et piles


Java n’a pas de types paramétrés comme C++. En java, il existe des classes pour représenter les
tableaux, les vecteurs et les piles. Ceux-ci, peuvent être composés d’objets ou de types primitifs. Ils
gèrent en fait les adresses des objets et non les objets eux-mêmes. Mais, l’implémentation en serait
moins efficace qu’en C++.

Même s’ils paraissent semblables, le comportement et la structure des tableaux sont différents en
Java et en C++. En Java, le tableau a un attribut « length », accessible en lecture seule, qui donne
la longueur du tableau. La taille des objets est donc fixée à l’écriture du programme et lors de la
compilation. Au moment de l’exécution, les limites de taille sont contrôlées et peuvent provoquer
une « exception » Java qui précède la violation de la mémoire du système. Ce mécanisme complète
la sécurité de la gestion de la mémoire décrit le paragraphe « gestion de mémoire ».

48. L’héritage
L’héritage a des caractéristiques proches en Java et en C++. En Java, il ne change pas le niveau de
protection. Contrairement à C++, Java n’utilise pas l’héritage multiple. Les fonctions de celui-ci
sont remplacées par l’implémentation des interfaces. Java n’a donc qu’une seule racine et une seule
hiérarchie de classe.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 41 / 49


49. Le multi threading
Java a la possibilité de gérer des processus légers multiples. Les exclusions mutuelles sont gérées
par le spécificateur synchronized.

50. Pas de pré-processeur


En Java, il n’y a pas de pré-processeur comme en C++. Il n’y a donc pas, en Java, de « #include »
(fonction que peut remplacer « import » de Java) ni la possibilité d’intégrer du macro langage dans
les programmes.

51. La gestion de la mémoire


Le « ramasse miettes » existe dans le langage Java et pas en C++. Il détruit automatiquement les
objets non utilisés. Il évite tous les problèmes de fuites de la mémoire.

Il n’y a pas de pointeurs en Java au sens où l’on peut les manipuler en C++. En revanche, il a bien
une gestion de pointeurs puisque les « handles » sont des variables qui contiennent l’adresse ou la
référence d’un objet. Mais le programmeur ne peut modifier cette adresse.

52. La gestion des erreurs et des exceptions


La récupération des exceptions est plus robuste en Java qu’en C++. En effet, en Java, au lieu
d’appeler une fonction simplement lors de l’exécution quand une mauvaise exception est lancée,
les spécifications des exceptions sont rendues obligatoires et contrôlées par le compilateur.

53. Autres différences : le « goto », les définitions préalables, la surcharge d’opérateurs


Il n’y a pas de « goto » en Java. Cependant, deux instructions « break » et « continue »
étiquetées permettent de sortir des boucles. Les définitions préalables ne sont pas nécessaires en
Java. Il n’autorise pas la surcharge d’opérateurs.

54. Méthodes natives


Java autorise les méthodes natives écrites en C ou en C++. Elles peuvent constituer une brèche
dans la sécurité des applications. C’est pourquoi, les « applets », ne peuvent, elles, utiliser des
méthodes natives.

55. Fonctions de documentation et librairies


Java a des fonctions intégrées de documentation. La documentation peut être extraite des
programmes et reformatée en HTML.

Java contient, en standard, des librairies pour la programmation réseau, la connexion à des bases de
données, le multithreading, la compression…. A partir de la version 1.1, il contient en standard des
fonctions de développement visuel. Java permet le développement de briques logicielles : les Beans
qui concourent à la ré-utilisabilité tant recherchée en programmation.

56. En conclusion
Java face à C++ présente les avantages suivants :

 Il est plus robuste et permet de développer des applications plus fiables et


mieux sécurisées.
 Il est plus cohérent vis à vis des concepts qu’il utilise, il est donc plus facile à
utiliser et à comprendre.
 Il facilite l’utilisation de composants et la ré-utilisabilité de ceux-ci. Il diminue
donc le temps de programmation.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 42 / 49


 Il est indépendant (ou presque) des plates-formes. Il est facile de l’intégrer
dans des milieux hétérogènes sans remettre tout l’existant de l’entreprise en
cause. De plus, il est possible d’installer la même version du code sur
différentes plates-formes « write once, run anywhere ».
Son principal inconvénient, pour les utilisations en mode interprétées, reste aujourd’hui ses
performances.

3.2. Tableau de synthèse


Nous sommes conscients que ce tableau est très imparfait et demanderait une étude beaucoup plus
approfondie. Nous avons choisi de le conserver malgré tout, non pas comme l’aboutissement d’une
étude, mais plutôt comme piste, permettant éventuellement de suivre l’évolution du langage Java.

Deux séries de critères sont retenus :

 Types d’applications : « applets », applications embarquées, applications


clientes, applications serveurs, développement de composants.
 Caractéristiques d’un bon langage (voir chapitre 1.4 « ce qu’on attend
aujourd’hui d’un langage de programmation) : fiabilité des logiciels produits,
standardisation et indépendance vis à vis des plates-formes, ré-utilisabilité et
richesse des bibliothèques, souplesse des représentations, simplicité et rapidité
de programmation, performances.

Types « Applets » et Applications Applications Développement de
d’applications composants clientes et micro- serveurs et composants
/ embarqués ordinateurs interfaces
Caractéristiques
Du langage
Fiabilité des Le langage étant Les logiciels Très bonne Les composants
logiciels produits robuste et sécurisé, produits en Java sont fiables, car ils
les appliquettes et sont moins peuvent être
composants fréquemment totalement
embarqués sont bogués. La encapsulés
fiables et sûrs. maintenance est
facilitée
Standardisation et Existe Réelle. Cependant, Dans le domaine Très apprécié : c’est
indépendances vis potentiellement. le quasi-monopole des serveurs la garantie que les
à vis des plates- L’implémentation de Microsoft donne d’applications, composants
formes de la JVM dépend malheureusement l’intégration facile pourront
cependant de la moins d’importance des briques Java en fonctionner en
bonne volonté des à cette possibilité. milieu hétérogène environnement
constructeurs de Le déploiement est est un atout hétérogène et
navigateurs. facilité. considérable. évolutif
Ré-utilisabilité et Possible et très Rend aujourd’hui Possible et très Possible et très
richesse des intéressante possible la intéressante intéressante
bibliothèques résolution de
problèmes jugés
hier trop complexes
ou trop coûteux
Souplesse des L’orienté objet permet un niveau d’abstraction de plus en plus élevé et donc une
représentations proximité accrue avec les problèmes réels.

Simplicité et La simplicité de Plus simple et L’utilisation des La rigueur des


rapidité de programmation est rapide (en EJB rend la concepts, ainsi que
programmation réelle. Java est particulier par réalisation des le développement
cependant considéré rapport à C++) si serveurs d’une approche
comme moins les concepts de  d'application plus programmation

CNAM – Examen probatoire – mai 1999 – le langage Java – page 43 / 49


abordable qu’un l’orienté objet sont simple et plus visuelle permet une
langage de script compris. rapide. relativement grande
comme JavaScript. L’utilisation des simplicité du
Beans facilite le développement des
travail. Beans.
Performances des Suffisantes, si on Suffisantes, si on Nombre d’accès Semblent
logiciels utilise l’interactivité utilise l’interactivité simultanés parfois suffisantes
pour optimiser les pour optimiser les insuffisants.
performances performances Nécessite des
serveurs puissants.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 44 / 49


Conclusion
Le langage Java est le résultat de multiples recherches qui ont marqué l’évolution permanente des
langages de programmation. Java a bénéficié de l’expérience des autres langages. Il a conservé un
peu le meilleur de chacun. Il est, me semble-t-il, le premier « vrai » langage orienté objet à pénétrer
de façon importante dans les entreprises. La pureté des concepts qu’il permet de manipuler, la
rigueur de son fonctionnement et la richesse de ses bibliothèques ne suffisent pas à expliquer son
succès. Java est aussi un langage non-propriétaire et indépendant des plates-formes. Il a été donné
par Sun à la communauté Internet et il est, aujourd’hui, soumis aux des instances de l’OSI pour
normalisation.

Le développement des langages orienté objet, en particulier du langage Java, marquera sans doute,
une étape dans l’histoire de l’informatique. Avec eux, il est possible de s’éloigner des contraintes
de la machine afin de mieux appréhender les problèmes du monde réel. Le développement des
« beans », véritables composants logiciels, et leurs utilisations dans certaines entreprises, illustre le
principe de ré-utilisabilité de l’orienté objet. Celui-ci présente deux avantages principaux : d’une
part, les développements informatiques auront désormais une « mémoire » bien formalisée et
d’autre part, l’utilisation de composants, dont la granularité augmente parce qu’ils peuvent
s’emboîter, permet d’élever le niveau d’abstraction des problèmes pouvant être résolus par
l’informatique.

Cette évolution des langages devrait apporter des changements dans la qualité des logiciels offerts
aux utilisateurs et dans l’étendu des problèmes traités par l’informatique. Ils modifieront peut être
l’organisation de la production des logiciels, en particulier, en rapprochant les métiers de
développeurs et de concepteurs.

Le développement futur du langage Java, avec ses objectifs actuels, est un enjeu de progrès social
pour les utilisateurs de l’informatique et les informaticiens. On ne peut que souhaiter qu’il ne soit
pas freiné par la concurrence économique.

CNAM – Examen probatoire – mai 1999 – le langage Java – page 45 / 49


Bibliographie
Livres
(Les ouvrages cités ci-dessous ont été étudiés partiellement par l’auteur du rapport)

JAVA™ IN A NUTSCHELL A Desktop Quick Reference – David Flanagan – Editions


O’REILLY – Second édition covers Java 1.1 - Mai 1997

Le développer Java™ 2 – Antoine Mirecourt – Editions Osman EYROLLES MULTIMEDIA –


Edition 1999

Java™ La synthèse Vers la maturité avec le JDK 1.2 – Gilles Clavel, Nicolas Mirouze, Sandrine
Munerot, Emmanuel Picon, Mohamed Soukal – Editions InterEditions – 2e édition 1998

Pour comprendre l’informatique. S’initier pour maîtriser – Michel Politis – Edition insep éditions

Thinking in Java – Bruce Eckel – (diffusion sur le Web au fomat PDF – chapitre «comparing C++
and Java )

Mémoire d’ingénieur CNAM


Concepts de base de l’orienté objet – C. Thomas

Revues
INFORMATIQUES Magazine Hors série N° 2 – Avril / Mai 1999 – Java dans l’entreprise

Sites Web
http://www.dejanews.com

http://www.sun.java.com

http://www.oreilly.com/catalog/javanut/

http://www.javaworld.com/

http://www.gamelan.com/

Cours du Cnam
LE LANGAGE JAVA – François-Yves Villemin - 1999

CNAM – Examen probatoire – mai 1999 – le langage Java – page 46 / 49


Table des matières
INTRODUCTION_______________________________________________________________________3

1. JAVA : UNE ÉTAPE DANS L’ÉVOLUTION DES LANGAGES DE PROGRAMMATION_____4

1.1. L’ORIGINE_______________________________________________________________________4
1.2. JAVA : LE LANGAGE DU TROISIÈME MILLÉNAIRE ?______________________________________4
1.3. L’ÉVOLUTION DES LANGAGES DE PROGRAMMATION____________________________________6
1.3.1. L’ASSEMBLEUR________________________________________________________________6
1.3.2. LES LANGAGES ÉVOLUÉS________________________________________________________6
1.3.2.1. Parmi les premiers langages évolués :__________________________________________7
1.3.2.2. Parmi les langages structurés :________________________________________________7
1.3.2.3. Parmi les langages fonctionnels :______________________________________________7
1.3.3. LE SENS DE L’ÉVOLUTION_______________________________________________________7
1.3.4. L’ÉVOLUTION DU CONTEXTE_____________________________________________________7
1.3.5. LES LANGAGES « ORIENTÉ OBJET »________________________________________________8
1.4. CE QU’ON ATTEND AUJOURD’HUI D’UN LANGAGE DE PROGRAMMATION____________________8
1.4.1. LA FIABILITÉ DES LOGICIELS PRODUITS_____________________________________________8
1.4.2. LA STANDARDISATION ET L’INDÉPENDANCE VIS À VIS DES PLATES-FORMES________________9
1.4.3. LA RÉ-UTILISABILITÉ ET LA RICHESSE DES BIBLIOTHÈQUES_____________________________9
1.4.4. LA SOUPLESSE DES REPRÉSENTATIONS______________________________________________9
1.4.5. LA SIMPLICITÉ ET RAPIDITÉ DE PROGRAMMATION_____________________________________9
1.4.6. LA PERFORMANCE DES LOGICIELS_________________________________________________9
1.5. LE LANGAGE JAVA : POURQUOI FAIRE ?______________________________________________9

2. LA DESCRIPTION DU LANGAGE JAVA_____________________________________________10

2.1. LA TECHNOLOGIE OBJET EN JAVA__________________________________________________10


2.1.1. LES OBJETS__________________________________________________________________10
2.1.1.1. Définition_______________________________________________________________10
2.1.1.2. L’objet dans le langage Java_________________________________________________10
2.1.2. LES CLASSES_________________________________________________________________12
2.1.2.1. Définition_______________________________________________________________12
2.1.2.2. Les classes en Java________________________________________________________12
2.1.3. L’ENCAPSULATION____________________________________________________________13
2.1.3.1. Définition_______________________________________________________________13
2.1.3.2. L’encapsulation en Java____________________________________________________14
2.1.4. L’HÉRITAGE_________________________________________________________________15
2.1.4.1. Définition_______________________________________________________________15
2.1.4.2. L’héritage en Java_________________________________________________________15
2.1.4.3. Les paquetages Java_______________________________________________________17
2.1.5. LE POLYMORPHISME ET LA SURCHARGE___________________________________________18
2.1.5.1. Définition_______________________________________________________________18

CNAM – Examen probatoire – mai 1999 – le langage Java – page 47 / 49


2.1.5.2. Le polymorphisme et la surcharge en Java______________________________________18
2.2. LA CONSTRUCTION D’UN PROGRAMME JAVA__________________________________________19
2.3. LA SYNTAXE DE JAVA____________________________________________________________19
2.3.1. LES TYPES___________________________________________________________________19
2.3.1.1. Les types primitifs________________________________________________________19
2.3.1.2. Les tableaux_____________________________________________________________19
2.3.1.3. Les chaînes______________________________________________________________20
2.3.1.4. Les opérateurs____________________________________________________________20
2.3.1.5. Les modificateurs_________________________________________________________20
2.3.1.6. Les structures de contrôles__________________________________________________21
2.4. LES « APPLETS »_________________________________________________________________22
2.4.1. QU’EST-CE QU’UNE « APPLET » ?_________________________________________________22
2.4.2. POURQUOI DES « APPLETS » ?___________________________________________________22
2.4.3. COMMENT PROGRAMMER UNE « APPLET » ?________________________________________22
2.4.4. LA GESTION DES ÉVÉNEMENTS___________________________________________________24
2.4.5. LA SÉCURITÉ DES « APPLETS »___________________________________________________24
2.5. LES INTERFACES GRAPHIQUES_____________________________________________________24
2.5.1. LE PAQUETAGE JAVA.AWT______________________________________________________24
2.5.2. LE PAQUETAGE JAVAX.SWING DE LA VERSION 2 DE JAVA______________________________26
2.6. LES ENTRÉES-SORTIES___________________________________________________________28
2.6.1. PRINCIPES GÉNÉRAUX__________________________________________________________28
2.6.2. LE PAQUETAGE JAVA.IO DE JAVA_________________________________________________28
2.6.3. LA SÉRIALISATION____________________________________________________________30
2.6.4. UN EXEMPLE : LECTURE ET ÉCRITURE D’UN FICHIER__________________________________30
2.7. LA GESTION DES EXCEPTIONS______________________________________________________31
2.7.1. QU’APPELLE-T-ON EXCEPTIONS ?_________________________________________________31
2.7.2. LES OBJETS EXCEPTIONS ET LA GESTION DES EXCEPTIONS EN JAVA______________________31
2.7.2.1. Attraper l’exception et la traiter______________________________________________32
2.7.2.2. Indiquer que la méthode est susceptible de générer une exception___________________32
2.7.3. UN EXEMPLE DE GESTION D’EXCEPTIONS___________________________________________32
2.8. LA GESTION DES PROCESSUS MULTIPLES LÉGERS « THREADS » (ACTIVITÉS)________________33
2.8.1. QU’EST-CE QUE LES « THREADS » ET À QUOI SERVENT-ILS ?____________________________33
2.8.2. LES ACTIVITÉS MULTIPLES (« THREADS ») DANS LE LANGAGE JAVA_____________________34
2.8.3. LA SYNCHRONISATION_________________________________________________________34
2.8.4. LA COMMUNICATION ENTRE ACTIVITÉS____________________________________________35
2.8.5. GROUPES DE « THREAD »_______________________________________________________35
2.9. LA COMMUNICATION RÉSEAU______________________________________________________36
2.9.1. A QUOI SET LA COMMUNICATION RÉSEAU ?_________________________________________36
2.9.2. LE PAQUETAGE JAVA.NET_______________________________________________________36
2.10. LES ÉVOLUTIONS RÉCENTES DE JAVA______________________________________________36
2.10.1. LES CLASSES INTERNES OU « INNER CLASS »________________________________________36
2.10.1.1. Les classes imbriquées_____________________________________________________36
2.10.1.2. Les classes membres_______________________________________________________37
2.10.1.3. Les classes locales________________________________________________________37
2.10.1.4. Les classes anonymes______________________________________________________37
2.10.2. LES JAVABEANS______________________________________________________________37
2.10.2.1. Qu’est-ce qu’un JavaBean ?_________________________________________________37
2.10.2.2. A quoi servent les JavaBeans ?_______________________________________________37
2.10.2.3. Le développement d’interfaces graphiques avec les JavaBeans______________________38
2.10.2.4. La construction de Beans___________________________________________________38
2.10.2.5. La gestion dynamique des objets : introspection ou la réflexion (reflection)____________38
2.10.2.6. Comment empaqueter un Bean ?_____________________________________________39
2.10.3. LA LIBRAIRIE JDBC ET LES ARCHITECTURES CLIENT/SERVEUR__________________________39
2.10.4. L’INTERNATIONALISATION______________________________________________________39
2.10.5. EN CONCLUSION______________________________________________________________40

CNAM – Examen probatoire – mai 1999 – le langage Java – page 48 / 49


2.11. LES ENVIRONNEMENTS DE DÉVELOPPEMENT JAVA___________________________________40

3. LES AVANTAGES ET LES INCONVÉNIENTS DU LANGAGE JAVA_____________________41

3.1. ELÉMENTS DE COMPARAISON AVEC C++_____________________________________________41


3.1.1. PERFORMANCES______________________________________________________________41
3.1.1.1. Les compilateurs natifs_____________________________________________________41
3.1.1.2. Les compilateurs de byte-code_______________________________________________41
3.1.1.3. Les compilateurs JIT (Just In Time)___________________________________________41
3.1.2. LES TYPES PRIMITIFS__________________________________________________________41
3.1.3. LES OBJETS ET CLASSES________________________________________________________41
3.1.4. LES TABLEAUX, VECTEURS ET PILES______________________________________________41
3.1.5. L’HÉRITAGE_________________________________________________________________42
3.1.6. LE MULTI THREADING__________________________________________________________42
3.1.7. PAS DE PRÉ-PROCESSEUR_______________________________________________________42
3.1.8. LA GESTION DE LA MÉMOIRE____________________________________________________42
3.1.9. LA GESTION DES ERREURS ET DES EXCEPTIONS______________________________________42
3.1.10. AUTRES DIFFÉRENCES : LE « GOTO », LES DÉFINITIONS PRÉALABLES, LA SURCHARGE
D’OPÉRATEURS__________________________________________________________________________42
3.1.11. MÉTHODES NATIVES___________________________________________________________42
3.1.12. FONCTIONS DE DOCUMENTATION ET LIBRAIRIES_____________________________________42
3.1.13. EN CONCLUSION______________________________________________________________43
3.2. TABLEAU DE SYNTHÈSE___________________________________________________________43

CONCLUSION________________________________________________________________________45

BIBLIOGRAPHIE______________________________________________________________________46

TABLE DES MATIÈRES________________________________________________________________47

CNAM – Examen probatoire – mai 1999 – le langage Java – page 49 / 49

Vous aimerez peut-être aussi