Langage JAVA : Syntaxe de base
Langage JAVA : Syntaxe de base avec exemples
...
Conventions d’écriture
Java • On utilise plutôt des minuscules
- Les noms commencent par des minuscules, sauf : identificateurs de classe : Frame, Button, String, ..
constantes symboliques : static final double PI = 3.14 ;
- Noms composés : getBack, taxMan, comeTogether, ..
- Les chaînes de caractères doivent être écrites sur une seule ligne
System.out.println ("Cou
Cou"); // Refusé !!
- Concaténation de textes: symbole « + »
System.out.println ("Cou" +
"Cou");// OK
int age = 20;
System.out.println ("J'ai " + 20 + "ans");
- Les caractères sont codés sur 16 bits !
Il s’agit du jeux de caractères UNICODE qui comprend la plupart des alphabets du monde. Ainsi, il est possible d’écrire les identificateurs avec des lettres accentuées : ouvrirFenêtre, commencerLaFête, ..
Ne pas écrire le nom des classes avec des accents. Chaque classe correspondra à un fichier (un fois le programme compilé), et les systèmes d’exploitation actuels ne reconnaissent pas forcément les accents dans les noms de fichiers.
- Commentaires
// commentaire court se terminant à la fin de la ligne
/*
Commentaire long. Imbrication non possible.
A n’utiliser que pour masquer des parties de programme (debugging), ou pour l’entête.
*/
Un commentaire long peut être utilisé aussi pour des commentaires très très courts au milieu d’une instruction !
Q System /* blabla*/ .out.println (“bla bla”);
2 Instruction d’affectation
Opérateur d'affectation
1) donne une nouvelle valeur à la variable,
2) retourne la valeur affectée
Exemple:
ada € a := b := c := 3 ; € INCORRECT java €a = b = c =3 ; € CORRECT
En Java, l’opérateur d’affectation a une « associativité » de type « R » (voir [Annexe A]) : cet opérateur s’exécute donc de la droite (Right) vers la gauche.
a = b = c = 3 ;
a = b = 3 ;
S'exécute en premier
1) "c" vaut 3
2) retourne 3
a = 3 ;
Retourne encore "3", mais cette fois-ci, cette valeur n'est plus utilisée.
...
10 Opérateur « instanceof »
Java Cet opérateur permet de contrôler le type d’un objet. Exemple : if (unObjet instanceof X) …
Cet opérateur retourne le booléen true si l’objet unObjet est de type X.
En l’occurrence, il retournera true dans les cas suivants :
1/ si unObjet est une instance de X (créé par new X())
2/ si unObjet est une instance d’une sous-classe de X (héritage)
3/ si unObjet est une instance d’une classe qui implémente X, au cas où X est une interface
11 Instruction composite : le « bloc »
Java Ce mécanisme permet de fabriquer une instruction à partir d’une séquence d’instructions, au moyen d’une paire d’accolades.
{
instruction ; instruction ;
… ; instruction ;
}
Ceci constitue une seule instruction
Par exemple, une procédure est constituée d’une en-tête et d’un bloc :
public void afficherX() {
System.out.println (x) ;
}
Syntaxe d’une procédure : en-tête uneInstruction
Autre exemple: un bloc pour écrire des if qui contiennent plusieurs instructions.
Exemple
if (x > 3) x=3;
Identique à
if (x > 3) {
x = 3;
autres instructions possibles..
}
Syntaxe du if : if (test) uneInstruction
12 La règle du point-virgule
Java Le point-virgule doit obligatoirement terminer chacune des instructions.
Une exception.. il n’est pas nécessaire de terminer les blocs par un point-virgule (l’accolade suffit !)
13 L’instruction « if »
Java Première forme €
if (test) uneInstruction
Deuxième forme €
if (test)
uneInstruction
else
uneAutreInstruction
- le test doit être écrit dans une paire de parenthèses
- ☺ il est fortement recommandé d’utiliser des blocs {..} pour écrire les instructions du if, même si les blocs ne contiennent qu’une seule instruction
Exemple no1 Exemple no2
int x, y1, y2 ; x=1 ;
if (x==0)
y1 = x; y2 = x;
x = y2;
que vaut x ? réponse : 1 int x, y1, y2 ; x=1 ;
if (x==0) {
y1 = x; y2 = x;
}
x = y2;
que vaut x ? réponse : 0
Java Le test doit retourner un booléen : c’est vérifié par le compilateur
Note C++ En C++, le type booléen n’existe pas !
Ce qui est égal à 0 est considéré comme faux, tout entier différent de 0 est considéré comme vrai ..
Ainsi, exécutez (dans votre tête) le programme C++ suivant.. que vaut x pour finir ?
int x = 3 ;
if (x=4) x++ ;
€ x ? réponse : 5
Essayez en Java, ce code sera refusé par le compilateur !
14 La pseudo clause « else if »
Java La clause « elsif » n’existe pas, ni en C++, ni en Java.
Mais il est possible de simuler cette clause..
En effet, la syntaxe de l’instruction if permet d’écrire la chose suivante :
if (x==0) {
action1 ;
}
else if (x==1) {
action2;
}
else if (x==3) {
action3;
}
else {
action4;
}
Voici le même programme écrit avec une autre indentation :
if (x==0) {
action1 ;
}
else if (x==1) {
action2;
}
else if (x==3) { action3;
}
else {
action4;
}
15 L’instruction « switch »
Java Supposons l’instruction suivante en Ada..
case x is
when 1..2 => y := 1;
when 4, 6 => y := 2;
when 5 => y := 3; when others => y := 4;
end case;
La même chose en Java, C++
un entier ou un caractère
entrées sorties
switch (x) {
case 1 :
autoroute
case 2 : y = 1 ;
break ;
case 4 :
case 6 : y = 2 ;
break ;
case 5 : y = 3 ;
break ;
default : y = 4 ;
}
Les instructions du switch sont exécutées en séquence. Comme pour une autoroute, il y a plusieurs entrées possibles, et plusieurs sorties possibles.. Pour les adaistes, attention à ne pas louper la sortie !
Java
16 Les boucles TANTQUE et REPETER
TANTQUE Test FAIRE
Instructions FIN_TANTQUE while(test)
uneInstruction;
Test Non Oui
Instructions ou (avec un bloc)
while(test) {
instruction 1;
instruction 2;
..
}
REPETER
Instructions TANTQUE Test do
uneInstruction;
while (test);
Instructions
Oui Test ou (avec un bloc)
Non
do{
instruction 1;
instruction 2;
..
}
while(test);
…
17 La boucle «for»
Java La boucle for est un while déguisé..
Syntaxe
for (initialisation ; condition_d’itération ; enchaînement) uneInstruction
équivalent à
initialisation ; while(condition_d’itération) {
uneInstruction; enchaînement ;
}
Exemple : afficher l’alphabet à l’envers
for (char c = ‘Z’; c >= ‘A’; c--) { System.out.print (c);
}
Même chose avec un «while»
char c = 'Z';
while (c >= 'A') { System.out.print (c); c--;
}
Encore une dernière fois avec «do»
char c = 'Z';
do {
System.out.print (c); c--;
}
while (c >= 'A');
Java A la différence de C++, et de manière identique à Ada -, si la boucle for contient dans sa partie d’initialisation une déclaration de variable, il s’agit d’une déclaration locale à la boucle : la variable n’existe plus après exécution de la boucle, sa portée est limitée à la boucle.
18 Contrôler l'exécution d'une boucle: break et continue
Java L’instruction break termine une instruction itérative (l’équivalent du « exit » de Ada):
while (true) {
..
..
if (x > 0) break ;
..
L’instruction continue termine l’itération en cours, mais la boucle continue de s’exécuter avec l’itération suivante.
while (! listeCaracteres.finListe()) { ch = liste.nextElement() ;
if (ch != ‘ ‘) continue; // ignorer
// le caractère
.. ;
}
19 Les types de données: objets et primitifs
Java Java distingue deux types de données:
19.1 PRIMITIFS
Le nom commence par une minuscule.
- entiers
int (32 bits), long (64 bits), short (16 bits) et byte(8 bits). Par défaut: int1
- réels
float et double (double précision, x chiffres significatifs) Par défaut: double2
- caractères
char (16 bits, selon le code UNICODE, qui comprend au départ le code ASCII)
- booléens
boolean (8 bits)
- Si on écrit «3», ce 3 est considéré comme une entité de type «int».
- Si on écrit «3.0», ce 3.0 est considéré comme une entité de type «double».
19.2 OBJETS
Instances de classes dont le nom commence par une majuscule.
tableaux String Frame Button
19.2.1 Manipulation par valeur, manipulation par référence
* Les primitifs sont manipulés par valeur, et les objets par référence (pointeurs) !
int x = 3; int y;
y = x; y = 4;
Que vaut x ? .. toujours 3 !
Les primitifs sont en effet manipulés par valeur. L’affectation d’un primitif opère une
copie de valeur : l’affectation y=x copie la valeur de x dans y.
Le même exemple avec des objets..
Button b2 = new Button ("OK");
Button b1; // Déclaration d’une variable b1 = b2; // Affectation de la variable b1.setLabel("Cancel");
Quel est le label du bouton b2 ? Q "Cancel". En modifiant b1, b2 a été modifié par la même occasion..
POURQUOI ?
Au contraire des primitifs, les objets sont manipulés par référence: les objets sont toujours créés dynamiquement, et les variables qui les désignent ne sont que des pointeurs sur les objets.
- Lorsque l'on déclare une variable de type objet, la variable est initialisée avec la valeur null (pointeur qui pointe sur rien du tout);
- Le programmeur a l'obligation de créer lui-même l'objet au moyen de l'opérateur new;
Button b2 = new Button ("OK");//Déclaration + création
ou
Button b2; // Déclaration
b2 = new Button("OK"); // Création
- Le même objet peut être pointé par plusieurs variables, et peut être manipulé au travers de l'une ou l'autre des variables.
b1 = b2;
Au contraire des primitifs, l’affectation opère un partage d’objets plutôt qu’une copie de valeur.
☺ Comment opérer une copie d’objets ? Q voir le point 46, page 64
- Le programmeur n'a pas besoin de détruire l'objet: il sera détruit automatique-
ment par le « garbage collector » de la machine virtuelle dès lors que cet objet ne sera plus pointé par une variable quelconque.
Exemple
public void p() { // Une procédure..
Button b = new Button("OK"); // Variable locale
à la procédure
} Q Fin d'exécution de la procédure
Q La variable locale b est détruite
Q L'objet sera détruit par le « garbage collecteur » (ramasse-miettes)
19.2.2 Valeur d'initialisation
Contrairement aux langages Ada ou C++, les primitifs et les objets reçoivent une valeur d'initialisation:
- Les primitifs sont initialisés avec la valeur 0
entiers Q0
réels Q0.0
booléens Qfalse
caractères Qcaractère « nul » (dont le code UNICODE vaut 0)
- Les variables de type objet sont des pointeurs initialisés avec la valeur null
20 Cycle de vie d’un objet
Considérons par exemple l’instruction: unObjet = new Xxx() ; La création de l’objet unObjet comprend 3 étapes :
1/ allocation d'une zone mémoire
Afin de contenir les variables d'instance de l'objet. Ces variables d'instances sont initialisées avec leurs valeurs par défaut ou par la valeur d'initialisation spécifiée par le programmeur lors de la déclaration de la variable.
Par exemple :
int i ; // "i" est initialisée à 0 (par défaut)
int j = 3 ; // "j" est initialisée avec 3
2/ invocation du constructeur (Xxx())
Lors de cette opération, de nouvelles valeurs peuvent être affectées aux variables d'instance et aux variables de classe. Voir aussi le point [Les constructeurs].
3/ retour de la référence
L’opérateur new retourne pour finir la référence à l’objet, qui sera affectée dans notre cas à la variable unObjet.
La destruction de l’objet est opérée par le ramasse-miettes (garbage collector). Cette opération est susceptible d’arriver dès l’instant où l’objet n’est plus référencé par aucune variable.
Avant même de détruire l’objet, le garbage collector envoie le message finalize() à cet objet, lui donnant ainsi l’occasion d’accomplir ses dernières volontés. L’utilisation de finalize(), qui joue le même rôle que le destructeur de C++, est effectuée très rarement en Java, du fait de l’existence même du garbage collector.
Le programmeur peut la redéfinir ainsi :
public void finalize () {
.../* dernières volontés ..*/
}
Voir aussi le point [Les destructeurs].
21 Les tableaux
Java Les tableaux de Java sont avant toute chose des objets. A ce titre, ils jouissent des particularités propres aux objets:
- ils sont manipulés par référence,
- ils sont alloués dynamiquement au moyen de l'opérateur new,
- ils sont récupérés automatiquement par le « ramasse-miettes » (le « garbage collector ») quand ils ne sont plus référencés,
- ils héritent de la classe «Object».
Toutefois, à la différence des « vrais » objets, il n’existe pas de classe correspondante (la classe Array n’existe pas !).
21.1 DÉCLARATION D'UN TABLEAU
int tabEntiers[]; // en utilisant la syntaxe de C/C++
// ou,
int [] tabEntiers; // en utilisant une syntaxe propre à Java
int [][] deuxDimensions; // tableau à deux dimensions
int troisDimensions [][][]; // tableau à trois dimensions
Les 3 tableaux déclarés ci-dessus sont de simples références initialisées à «null». Les tableaux eux-mêmes (des objets) ne sont pas encore créés. C'est au moment de leur allocation dynamique que l'on pourra spécifier leur taille.
21.2 CRÉATION DYNAMIQUE DES OBJETS « TABLEAU »
La création d'un objet de type tableau peut être réalisée de deux manières:
- Avec l'opérateur new, en indiquant le nombre de cases du tableau
int [] tabEntiers; // Déclaration
tabEntiers = new int[4]; // Création: 4 entiers
// initialisés à 0
// OU,
int [] tabEntiers = new int[4]; // en une seule
// instruction..
Les éléments d'un tableau reçoivent une valeur initiale qui correspond à la valeur par défaut du type des éléments du tableau : («0» pour un tableau d'entiers, «null» pour des objets ou des tableaux, ..
- Au moyen d'un « initialiseur ».
int x = 4 ;
int [] tabEntiers = {1, x, 2*x, 4};
// Tableau de 4 entiers, initialisés à 1, 4, 8 et 4
L'initialiseur doit être utilisé au moment de la déclaration. Il est interdit dans le cadre d'une affectation. L'instruction ci-après est illégale.
int [] tab ;
tab = {1, 2} ; // Illégal !!
21.3 ACCÈS AUX ÉLÉMENTS D'UN TABLEAU
Les tableaux sont indexés par des valeurs de type «int», en commençant à «0». Des indices de type «long» ne sont pas autorisés. La taille des tableaux est donc limitée à 32 bits !
tabEntiers [3] = 4;
System.out.println (tabEntiers [0]);
)A l'exécution, si l'indice sort des limites du tableau, le noyau Java lève l'exception :
«ArrayIndexOutOfBoundsException».
21.4 LA TAILLE D'UN TABLEAU
Les tableaux sont des objets, et ils disposent d'un attribut (un seul) qui caractérise leur taille : l'attribut length.
Voici un fragment de programme qui initialise tous les éléments du tableau tab avec la valeur 2 :
for (int cpt = 0 ; cpt < tab.length ; cpt++) { tab [cpt] = 2 ;
}
)Attention ! rappelons que l'indice d'un tableau commence par «0».
Ainsi, l'instruction «tab[tab.length]=3;» lèvera l'exception «ArrayIndex-OutOfBoundsException»
)La taille d'un tableau est statique1: le nombre des éléments ne peut pas être augmenté ni diminué dynamiquement, au grès des besoins.
21.5 UN TABLEAU COMME ARGUMENT DE MÉTHODE
Un paramètre formel de type tableau sera spécifié en utilisant la même syntaxe que pour la déclaration d'un tableau :
void uneProcédure (int [] tabEntiers) {
// Cette procédure diminue de 1 tous les éléments
// du tableau
for(int cpt=0; cpt < tabEntiers.length ; cpt++) {
tabEntiers [cpt] --;
}
}
21.6 UN TABLEAU COMME TYPE DE RETOUR
Une fonction peut retourner un tableau. Voici par exemple l'entête d'une telle fonction :
int [] uneFonction () {
// Fonction retournant un tableau d'entiers
- La classe « Vector » du paquetage « java.util » met en œuvre des listes dynamiques et permet ainsi de manipuler des tableaux de taille variable
return unTableauDEntiers ;
}
21.7 TABLEAUX À DIMENSIONS MULTIPLES
Les « initialiseurs » de tableaux peuvent être imbriqués :
int [][] deuxDimensions = { {1, 2}, {3, 4}, {5, 6} } ;
équivalent à :
int [][] deuxDimensions = new int [3][2] ;
deuxDimensions [0][0] = 1 ;
deuxDimensions [0][1] = 2 ;
deuxDimensions [1][0] = 3 ;
...
- La création d'un tableau à dimensions multiples peut être opérée en une étape
int [][] tab = new int [2][3] ;
- ou en plusieurs étapes :
int [][] tab = new int [2][] ;
// Création d'un tableau de deux éléments dont le type
// est "int []", initialisés à "null" pour l'instant
tab[0] = new int [3] ; tab[1] = new int [4] ;
// On remarque dans cet exemple que ce tableau à deux
// dimensions n'est pas une matrice carrée ! !
tab [0][2] = 120 ;
// Accès à un élément du tableau à deux dimensions
// Le raccourcit "tab [0, 2]" à la "pascal" n'est pas
// prévu dans Java.
tab
22 Les chaînes de caractères (String)
En Java, les chaînes de caractères ne sont pas des tableaux de caractères !
En Java, on sait simplement que les chaînes sont des objets, des instances de la classe
«java.lang.String ».
En tant que chaînes, ces objets jouissent toutefois de deux particularités :
- Il est possible de les créer au moyen d'un initialiseur (texte écrit entre guillemets), sans passer par l'opérateur «new».
String txt = "Salut";
- Java définit un opérateur de concaténation: l'opérateur «+»
System.out.println ("2 + 3 = " + (2+3) + " !");
Dans une expression qui comprend « l'addition » de plusieurs opérandes, il suffit que l'un d'entre eux soit de type String, pour que les autres opérandes soient automatiquement convertis en String (si cette conversion est possible).
Voici quelque méthodes proposées par la classe String:
Soit la chaîne «s» : String s = "Salut ";
- s.length()
Retourne le nombre de caractères de «s»
- s.charAt(1)
Retourne «a», le caractère de rang «1». Le rang d'un caractère va de 0 à (s.length()-1)
- s.equals(uneAutreChaîne)
Retourne «true» si les deux chaînes ont la même valeur
- s.compareTo(uneAutreChaîne)
Retourne «-1» (si plus petite que..), «0» ou «1»
- s.indexOf (uneSousChaîne, depuisUnIndex)
Retourne la position de la sous-chaîne
- s.concat (uneAutreChaîne)
Retourne une chaîne résultant de la concaténation avec une autre chaîne
- s.trim ()
Retourne une chaîne sans les espaces de début et de fin
- s.toUpperCase ()
Retourne une chaîne transformée en majuscules
Pour comparer le contenu de deux chaînes de caractères, utiliser la fonction equals : if (s1.equals(s2))…
Une simple comparaison ne marchera pas : if (s1==s2) .. (comparaison de pointeurs !!)
Une chaîne de caractères est un objet non mutable : son contenu est défini une fois pour toutes par l’initialiseur.
…
26 Conversions de types
26.1 PRIMITIFS # PRIMITIFS
Toutes les conversions sont autorisées, sauf celles qui font intervenir le type boolean. Les conversions qui entraînent un rétrécissement comme par exemple :
- une perte de précision: « réel Ð entier »
- une réduction du nombre de bits: « int (32 bits) Ð short (16 bits)», etc.. réclament obligatoirement une coercition de type: (type). La coercition de type est une espèce d’avertissement au programmeur : elle n’empêchera pas le programme de « planter » à l'exécution le cas échéant, voir ci-après.
Les conversions sans risque, celles qui n'entraînent pas de rétrécissement, sont opérées automatiquement.
- entier # entier
int i = s; // Avec "s" de type short
// c pas de rétrécissement
short s = (short) i;// Réduction du nombre de bits !
// Plante à l’exécution si "i" utilise plus de 16 bits
etc..
- réel # entier
double d = i; // Avec "i" de type entier pas de rétrécissement
int i = (int)d; // Rétrécissement avec troncation des chiffres
// après la virgule
- int (32 bits) # char (16 bits unicode)
int i = 'A'; // Unicode de 'A' (65) affecté à "i"
char c = (char)65; // Valeur 'A' affectée à "i"
// Coercition obligatoire car réduction
// du nombre de bits !
- etc..
26.2 PRIMITIFS NUMÉRIQUES # STRINGS
- Ð Strings
String s = unNumérique + ""; Concaténation avec un texte vide
ou: String s = String.valueOf(unNumérique);
- Ð Numériques
int i = (new Integer(unString)).intValue(); double d = (new Double(unString)).doubleValue(); float f = (new Float(unString)).floatValue(); etc..
26.3 CHAR # STRING
String s = new String (c); // avec "c" de type char char c = s.charAt(indice); // avec "s" de type String
26.4 BOOLEAN # STRING
boolean b = Boolean.getBoolean (unString) ; String s = String.valueOf(unBooléen);
26.5 PRIMITIFS # OBJET
Cette conversion utilise les classes "wrappers" spécifiques, qui permettent d'encapsuler le primitif correspondant.
primitif classe wrapper correspondante
int Integer
double Double
char Character
…
27 Procédures, fonctions et envoi de message
Java Les procédures et fonctions sont des regroupements d’instructions sous le même nom. En POO, les fonctions et procédures sont regroupées sous un seul terme : on parle de méthodes.
Pour exécuter les instructions d’une méthode, il nous faut invoquer cette dernière en envoyant le message correspondant à l’objet sur lequel opère la méthode:
objet.message(paramètres)
Pour envoyer un message, il faut :
1/ écrire le nom de l’objet, 2/ écrire un point,
3/ écrire le nom de la méthode, en écrivant les paramètres entre parenthèses.
En C++ comme en Java, les parenthèses sont obligatoires, même s’il n’y a pas de paramètre à écrire.
Exemples
unRectangle.getLargeur() ; unePile.vider() …
28 Pour s’envoyer un message: «this»
Si on omet d’écrire le nom de l’objet, cela signifie que le mot «this» est sousentendu : le message est envoyé à « lui-même » (un message est toujours envoyé par un objet à un objet).
Exemple:
vider();
équivalent à:
this.vider();
29 Méthodes d’instance et méthodes de classe
Java Dans la majorité des cas, les messages sont envoyés à des objets (des instances de classes).
Certains messages seront toutefois envoyés à la classe elle-même directement.
Ces dernières méthodes sont appelées méthodes de classe, les autres étant désignées par le terme méthodes d’instance. La déclaration d'une méthode de classe comporte le mot-clé static.
Un premier exemple : la fonction « main » dans un programme avec 2 classes
class Y {
public void yP1() {
System.out.println("yP1:je suis une methode d'instance "); yP2();// Correct
}
public static void yP2() {
System.out.println("yP2:je suis une methode de classe"); yP1();// REFUSE ! (voir ci-après)
}
}
public class X {
public void xP1() {
System.out.println("xP1:je suis une methode d'instance "); xP2();// Correct
}
public static void xP2 () {
System.out.println("xP2:je suis une methode de classe"); xP1();// REFUSE !(voir ci-après)
}
public static void main (String [] arg) {
// "main" est une méthode de classe Y unObjet = new Y();
unObjet.yP2();// Invocation d'une méthode d'instance
Y.yP1(); // Invocation d'une méthode de classe
xP1(); // REFUSE ! (voir ci-après)
xP2(); // Correct
}
}
Invocation des méthodes d'une classe depuis l'extérieur de la classe
- Invocation d'une méthode d'instance (yP1) Y uneInstance = new Y(); uneInstance.yP1();
- Invocation d'une de méthode de classe (yP2)
Y.yP2();
Par exemple, au lancement du programme, la machine virtuelle envoie le message main directement à la classe X: X.main(arguments)
Invocation des méthodes d'une classe depuis l'intérieur de la classe
☺ Une méthode d'instance peut invoquer des méthodes d'instance ou des méthodes de classe
/ Une méthode de classe ne peut invoquer que des méthodes de classe !
POURQUOI CETTE LIMITATION ? à ce stade, cela peut paraître curieux.. Ainsi, la fonction main ne peut pas invoquer de méthode d’instance !
Q nous reprendrons la question dans le point [Variables de classes et variables d’instance].
…
30.2 DÉCLARATION D’UNE PROCÉDURE
En ada
procedure AfficherTableau (tab: array of integer) is begin
for cpt in 1..tab’length loop put (tab(cpt));