Introduction a La Programmation Java
Introduction a La Programmation Java
HISTORIQUE DU LANGAGE
1 Qu’est-ce que le langage Java ?
Programmer en Java revient à écrire des lignes de code source dans le langage Java. Ce
langage de programmation est assez facile à comprendre par les humains. Il est orienté
objets et strictement basé sur des classes. La syntaxe du langage s’inspire volontairement de
celle des deux prédécesseurs que sont les langages C et C++. L’objectif, qui a été atteint,
consistait au départ à faire de Java un langage assez familier aux yeux des programmeurs qui
pratiquaient déjà ces deux autres langages.
La machine virtuelle JVM (Java Virtual Machine) est un logiciel qui constitue un
environnement technique permettant d’exécuter un programme Java. Autrement dit, il est
impossible d’exécuter un programme Java sur un ordinateur sur lequel n’a pas été installée
une machine JVM correspondant au matériel et au système d’exploitation.
La JVM a été produite pour de nombreux environnements matériels, de l’ordinateur
personnel sous Windows au boîtier Internet posé sur le téléviseur, en passant par les
lecteurs de DVD Blu-ray et les grands systèmes de calcul scientifique.
Vous pouvez démarrer un programme Java depuis une ligne de commande en mode texte,
de la manière suivante : java <paramètre> nomProgramme
Cette commande provoque le démarrage de la machine JVM sous forme d’un processus du
système d’exploitation de l’ordinateur physique. Elle met en place l’environnement
d’exécution Java puis démarre l’exécution du programme dans cette machine virtuelle
venant de démarrer, et donc vide de tout autre programme.
La machine virtuelle JVM n’est pas un interpréteur au sens habituel : le format du code qui
lui est fourni pour exécution n’est pas du code source Java. Le code source Java doit avoir
été converti, compilé en quelque sorte, vers un format intermédiaire qui est appelé le
bytecode ou octocode Java. Le fichier au format bytecode Java doit être fourni en entrée de
la JVM dans un format appelé format de fichier de classe, le nom de fichier portant toujours
l’extension .class.
Pour mieux comprendre comment du code source Java est compilé puis exécuté, et en quoi
Java se distingue de la plupart des autres environnements de programmation, étudions la
chaîne de traitement représenté en Figure 1.1.
Les nouveaux fichiers de classes peuvent être ajoutés à un programme existant grâce au
mécanisme de chargement de classe (classloading). Grâce à ce mécanisme, le nouveau type
incarné par la classe devient accessible à l’interpréteur pour qu’il en exécute le contenu.
Répondons par avance aux questions qui reviennent le plus fréquemment à propos du cycle
de vie d’un programme Java et des détails de son exécution.
Le concept de machine virtuelle Java JVM consiste à proposer une sorte de microprocesseur
logiciel, autrement dit un processeur dans le processeur physique. Le code intermédiaire
octocode (bytecode) est tout simplement du code machine destiné à être exécuté par cette
machine virtuelle. Pendant l’exécution, la JVM traduit à très grande vitesse les instructions
octocode en codes opératoires pour le processeur physique.
Les choix de conception du format octocode sont donc totalement guidés par le besoin de
faire exécuter cet octocode efficacement par l’interpréteur dans la machine JVM.
Un compilateur produit du code binaire, c’est-à-dire des instructions machine. L’outil Java
javac produit de l'octocode stocké dans des fichiers de classes, ce qui n’est pas la même
chose. Cela dit, les fichiers de classes peuvent être comparés à des fichiers intermédiaires
objets tels que les fichiers .dll de Windows ou les fichiers .so de Unix. Dans tous les cas, le
contenu n’est pas lisible par des humains.
En théorie informatique, l’outil javac correspond à la première partie du compilateur, celle
qui produit la représentation intermédiaire qui est ensuite utilisée pour obtenir le code
machine.
Le terme octocode désigne un code sur un seul octet (byte, donc un octocode). Les pseudo-
instructions sont ainsi codées sur un seul octet à l’intention de la machine virtuelle JVM.
Certaines opérations sont suivies d’octets supplémentaires pour les paramètres. Dans tous
les cas, il n’y a que 256 octocodes possibles. En pratique, seuls 200 sont utilisés, et
certaines valeurs ne sont plus exploitées dans les plus récentes versions de javac.
Le format octocode ne change jamais, quelle que soit la machine pour laquelle il est généré
(c’est sa raison d’être). Même l’ordre de stockage des bits au sein des octets (le boutisme,
que l’on appelle également endianness) est constant. Les plus curieux d’entre vous seront
heureux d’apprendre que les bits sont toujours stockés dans le sens big endian : les bits de
poids fort en premier.
La machine virtuelle JVM est un interpréteur, même si les performances sont fortement
améliorées grâce à la compilation à la volée JIT. Java se distingue de la plupart des langages
interprétés tels que PHP, Perl, Ruby ou Python qui interprètent réellement depuis le code
source vers le code machine, en général en générant un arbre syntactique abstrait à partir
du code source. En revanche, l’interpréteur JVM attend en entrée des fichiers de classes,
fichiers qui ont été produits par l’outil javac dans une sorte de précompilation.
CHAPITRE2 GENERALITES
1 Premier exemple de programme Java
Voici un exemple très simple de programme qui se contente d’afficher dans la fenêtre
console le texte : "Mon premier programme Java".
Là encore, une première ligne identifie la méthode ; elle est suivie d’un bloc ({ ..... }) qui en
fournit les différentes instructions.
Pour l’instant, vous pouvez vous contenter d’utiliser un tel canevas, sans vraiment connaître
les notions de classe et de méthode. Il vous suffit simplement de placer dans le bloc le plus
interne les instructions de votre choix, comme vous le feriez dans le programme principal
(ou la fonction principale) d’un autre langage.
Pour l’instant, vous pouvez vous contenter de considérer que System.out.println correspond
à une méthode d’affichage dans la fenêtre console, méthode à laquelle on mentionne un
texte à afficher sous forme d’une constante chaîne usuelle (entre guillemets, comme dans la
plupart des langages).
Il existe également une méthode System.out.print qui fait la même chose, avec cette seule
différence qu’elle ne provoque pas de changement de ligne après affichage. Ainsi, l’unique
instruction de notre programme pourrait être (artificiellement) remplacée par :
Ensuite, on procède à la compilation de ce fichier source. Rappelons que celle-ci produit non
pas du code machine, mais un code intermédiaire formé de bytecodes. Si la compilation s’est
bien déroulée, on obtiendra un fichier portant le même nom que le fichier source et
l’extension class, donc ici PremProg.class. On pourra lancer l’exécution des byte codes ainsi
obtenus par l’intermédiaire de la machine virtuelle Java. Bien entendu, on pourra exécuter
autant de fois qu’on le voudra un même programme, sans avoir besoin de le recompiler.
La démarche à employer pour procéder à ces différentes étapes dépend tout naturellement
de l’environnement de développement avec lequel on travaille. S’il s’agit du JDK2 de SUN, on
compilera avec la commande :
javac PremProg.java
java PremProg
À la suite de cette dernière commande, on obtiendra les résultats dans la même fenêtre, qui
ressemblera donc à ceci (en fait, les commandes seront probablement précédées d’un
"prompt") :
javac PremProg.java
java PremProg
Mon premier programme Java
-------------------------------------------------
n = 5
x = 11.5
valeur de y : 69.5
Bien entendu, nous avons utilisé le même canevas que précédemment avec un autre nom de
classe (ici Exemple) :
Les deux premières instructions de notre fonction main sont des déclarations classiques :
int n ;
double x ;
La première précise que la variable n est de type int, c’est-à-dire qu’elle est destinée à
contenir des nombres entiers (relatifs). Comme la plupart des langages, Java dispose de
plusieurs types entiers. De la même manière, la seconde instruction précise que x est une
variable de type double, c’est-à-dire destinée à contenir des nombres flottants en "double
précision" (approximation de nombres réels). Nous verrons que Java dispose de deux types
de flottants, le second se nommant float (nous ne l’avons pas utilisé ici car il aurait fait
intervenir des problèmes de conversion des constantes flottantes).
Comme dans la plupart des langages modernes, les déclarations sont obligatoires en Java.
Cependant, il n’est pas nécessaire qu’elles soient regroupées en début de programme
(comme cela est le cas en C ou en Pascal) ; il suffit simplement qu’une variable ait été
déclarée avant d’être utilisée.
n=5;
x = 2*n + 1.5 ;
Les deux instructions suivantes font appel à la fonction System.out.println déjà entrevue au
paragraphe 1 :
Mais cette fois, vous constatez que son argument ne se limite plus à une simple constante
chaîne. En Java, l’expression "n = " + n est interprétée comme la concaténation de la chaîne
constante "n = " avec le résultat de la conversion en chaîne de la valeur de la variable n. Une
telle conversion fournit en fait la suite de caractères correspondant à l’écriture du nombre
en décimal.
La même remarque s’applique à l’expression "x = " + x. Nous verrons que l’opérateur +
possède une propriété intéressante : dès que l’un de ses deux opérandes est de type chaîne,
l’autre est converti en chaîne.
Java est avant tout destinée à développer des applications ou des applets utilisant des
interfaces graphiques. Mais comme nous l’avons déjà signalé, la programmation des
interfaces graphiques nécessite de nombreuses connaissances, y compris celles relatives à la
programmation orientée objet. Pour faciliter l’apprentissage du langage, il est de loin
préférable de commencer par réaliser des programmes travaillant en mode console.
Comme nous l’avons vu précédemment, l’affichage dans la fenêtre console ne présente pas
de difficultés puisqu’il suffit de recourir à l’une des fonctions system.out.println ou
system.out.print. Malheureusement, Java ne prévoit rien de comparable pour la lecture au
clavier.
En fait, il est toujours possible de développer une petite classe offrant les services de base
que sont la lecture d’un entier, d’un flottant ou d’un caractère. Vous trouverez une telle
classe sous le nom Clavier.java ainsi que sa liste complète en annexe B. Il n’est pas
nécessaire de chercher à en comprendre le fonctionnement pour l’instant. Il vous suffit de
savoir qu’elle contient des fonctions de lecture au clavier, parmi lesquelles :
Ainsi, voici comment nous pourrions demander à l’utilisateur de fournir un nombre entier
qu’on place dans la variable nb :
int nb ;
.....
System.out.print ("donnez un nombre entier : ") ;
nb = Clavier.lireInt() ; // () obligatoires pour une fonction sans arguments
Nous utiliserons les possibilités de cette classe Clavier dans notre prochain exemple de
programme.
Notez que nous nous sommes limités à la lecture d’une seule valeur par ligne. D’autre part,
si l’utilisateur fournit une réponse incorrecte, nous avons prévu que le programme
s’interrompe avec le message : *** Erreur de donnee ***.
Pour pouvoir utiliser cette classe Clavier au sein d’un de vos programmes, vous disposez de
plusieurs solutions. Pendant la phase d’apprentissage du langage, la démarche la plus simple
consiste à :
Recopier le fichier source Clavier.java dans le même répertoire que celui où se trouve le
programme l’utilisant,
Compiler une seule fois ce fichier.
Par la suite, la classe Clavier.class sera automatiquement utilisée dès que vous compilerez
une autre classe y faisant appel.
Avec certains environnements intégrés, vous aurez peut-être besoin de mentionner cette
classe Clavier.java au sein d’un fichier projet. En revanche, il ne sera plus nécessaire qu’elle
figure dans le même répertoire que le programme l’utilisant.
Remarque :
Comme vous le verrez dans le chapitre relatif aux classes, vous pourrez également utiliser la
classe Clavier en le collant à la suite de votre fichier source, de manière à obtenir deux
classes dans un même fichier. Dans ce cas, toutefois, il vous faudra supprimer le mot-clé
public de la ligne public Class Clavier.
int i ;
double x ;
double racx ;
system.out.println ("Bonjour") ;
System.out.println ("Je vais vous calculer " + NFOIS + " racines carrees");
if (x < 0.0)
System.out.println (x + " ne possede pas de racine carree");
else
{ racx = Math.sqrt(x) ;
System.out.println (x + " a pour racine carree : " + racx);
}
}
System.out.println ("Travail termine - Au revoir") ;
}
----------------------------
Je vais vous calculer 5 racines carrees
Donnez un nombre : 16
16.0 a pour racine carree : 4.0
Donnez un nombre : 2
2.0 a pour racine carree : 1.4142135623730951
Donnez un nombre : -9
-9.0 ne possede pas de racine carree
Donnez un nombre : 5.25
5.25 a pour racine carree : 2.29128784747792
Donnez un nombre : 2.25
2.25 a pour racine carree : 1.5
Travail termine - Au revoir
En Java comme dans la plupart des langages, il existe plusieurs façons d’effectuer une
répétition. Ici, nous avons utilisé l’instruction for que les connaisseurs du C n’auront aucun
mal à interpréter :
Son rôle est de répéter le bloc (délimité par des accolades { et }) figurant à sa suite, en
respectant les consignes suivantes :
Comme C, Java dispose d’une notation d’incrémentation. Ici, i++ est équivalente à i = i+1.
Les lignes :
if (x < 0.0)
System.out.println (x + " ne possede pas de racine carree");
else
{ racx = Math.sqrt(x) ;
System.out.println (x + " a pour racine carree : " + racx);
}
Constituent une instruction de choix basée sur la condition x <0.0. Si cette dernière est vraie,
on exécute l’instruction suivante :
Si elle est fausse, on exécute l’instruction suivant le mot else, c’est-à-dire ici le bloc :
{ racx = Math.sqrt(x) ;
System.out.println (x + " a pour racine carree : " + racx) ;
}
Notez l’appel de la fonction Math.sqrt qui fournit une valeur de type double, correspondant
à la racine carrée de la valeur (de type double) qu’on lui fournit en argument.
Comme les autres langages, Java distingue les instructions de déclaration (fournissant des
informations au compilateur pour qu’il mène à bien sa traduction) et les instructions
exécutables (dont la traduction fournit des instructions en code machine, ou plutôt ici en
byte codes). Cependant, nous verrons que la liberté offerte dans l’emplacement des
déclarations conduit à les rendre partiellement exécutables.
Quant aux instructions exécutables, nous verrons qu’on peut les classer selon trois catégories :
Les deux dernières ont une définition "récursive" puisqu’elles peuvent contenir, à leur tour,
n’importe laquelle des trois formes.
Aucune limitation ne pèse sur le nombre de caractères, qui sont tous significatifs (en C, seuls
les 32 premiers l’étaient).
Notez bien que, comme en C (et contrairement à Pascal), on distingue les majuscules des
minuscules. Ainsi, Ligne et ligne désignent deux identificateurs différents ; il en va de même
pour PremProg et Premprog.
Certains mots-clés sont réservés par le langage à un usage bien défini et ne peuvent pas être
utilisés comme identificateurs. En voici la liste, par ordre alphabétique :
Dans notre langue écrite, les mots sont séparés par un espace, un signe de ponctuation ou
une fin de ligne.
int x,y
par
intx,y
int n,compte,p,total,valeur ;
voire :
Comme tout langage évolué, Java autorise la présence de commentaires dans les
programmes source. Ces textes explicatifs destinés aux lecteurs du programme n’ont aucune
incidence sur sa compilation. Java dispose de deux formes de commentaires :