<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> <TITLE>  Java </TITLE> </HEAD> <BODY BGCOLOR=white TEXT=black> <A HREF="main012.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A> <A HREF="main014.html"><IMG SRC ="next_motif.gif" ALT="Next"></A> <A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A> <HR>  <H1>Annexe&nbsp;A&nbsp;&nbsp;&nbsp;&nbsp;Java</H1>Le langage Java a t conu par Gosling et ses collgues  Sun microsystems comme une simplification du C++ de Stroustrup [<CITE><A HREF="main016.html#c++"><CITE>49</CITE></A></CITE>]. Le langage, prvu initialement pour programmer de petits automatismes, s'est vite retrouv comme le langage de programmation du World Wide Web, car son interprteur a t intgr dans pratiquement tous les navigateurs existants. Il se distingue de C++ par son typage fort (il n'y pas par exemple de possibilit de changer le type d'une donne sans vrifications) et par son systme de rcupration automatique de la mmoire (glaneur de cellules ou GC ou <EM>garbage collector</EM> en anglais). Trs rapidement, le langage est devenu trs populaire, quoiqu'ayant besoin d'une technologie de compilation plus avance que C++. De multiples livres le dcrivent, et il est un peu vain de vouloir les rsumer ici. Parmi ces livres, les plus intressants nous semblent dans l'ordre [j1,j2,j3,j4]. <BR> <BR> Comme C++, Java fait partie des langages orients-objets, dont les anctres sont le Simula-67 de Dhal et Nygaard et Smalltalk de Deutsch, Kay, Goldberg et Ingalls [<CITE><A HREF="main016.html#smalltalk"><CITE>13</CITE></A></CITE>], auquel il faut adjoindre les nombreuses extensions objets de langages prexistants comme Mesa, Cedar, Modula-3, Common Lisp, Caml. Cette technique de programmation peu utilise dans notre cours (mais enseigne en cours de majeure) a de nombreux fans, et est mme devenu un argument commercial pour la diffusion d'un langage de programmation.<BR> <BR> <A NAME="toc52"></A> <H2>A.1&nbsp;&nbsp;Un exemple simple</H2>Considrons l'exemple des carrs magiques. Un carr magique est une matrice <I>a</I> carre de dimension <I>n</I>  <I>n</I> telle que la somme des lignes, des colonnes, et des deux diagonales soient les mmes. Si <I>n</I> est impair, on met 1 au milieu de la dernire ligne en <I>a</I><SUB><FONT SIZE=2><I>n</I>, <FONT FACE=symbol></FONT> <I>n</I>/2 <FONT FACE=symbol></FONT> + 1</FONT></SUB>. On suit la premire diagonale (modulo <I>n</I>) en mettant 2, 3, .... Ds qu'on rencontre un lment dj vu, on monte d'une ligne dans la matrice, et on recommence. Ainsi voici des carrs magiques d'ordre 3, 5, 7<BR> <BR> <DIV ALIGN=center> <TABLE CELLSPACING=0 CELLPADDING=0> <TR VALIGN=middle><TD nowrap> <TABLE CELLSPACING=2 CELLPADDING=0> <TR><TD ALIGN=center></TD><TD NOWRAP ALIGN=left> <TABLE CELLSPACING=0 CELLPADDING=0> <TR VALIGN=middle><TD nowrap><FONT FACE=symbol> <BR> <BR> <BR> <BR> </FONT> </TD><TD nowrap> <TABLE CELLSPACING=2 CELLPADDING=0> <TR><TD NOWRAP ALIGN=right>4</TD><TD NOWRAP ALIGN=right>9</TD><TD NOWRAP ALIGN=right>2</TD></TR> <TR><TD NOWRAP ALIGN=right>3</TD><TD NOWRAP ALIGN=right>5</TD><TD NOWRAP ALIGN=right>7</TD></TR> <TR><TD NOWRAP ALIGN=right>8</TD><TD NOWRAP ALIGN=right>1</TD><TD NOWRAP ALIGN=right>6 </TD></TR></TABLE></TD><TD nowrap> </TD><TD nowrap><FONT FACE=symbol> <BR> <BR> <BR> <BR> </FONT> </TD></TR></TABLE></TD><TD ALIGN=center>&nbsp;&nbsp;</TD><TD NOWRAP ALIGN=left> <TABLE CELLSPACING=0 CELLPADDING=0> <TR VALIGN=middle><TD nowrap><FONT FACE=symbol> <BR> <BR> <BR> <BR> <BR> <BR> </FONT> </TD><TD nowrap> <TABLE CELLSPACING=2 CELLPADDING=0> <TR><TD NOWRAP ALIGN=right>11</TD><TD NOWRAP ALIGN=right>18</TD><TD NOWRAP ALIGN=right>25</TD><TD NOWRAP ALIGN=right>2</TD><TD NOWRAP ALIGN=right>9</TD></TR> <TR><TD NOWRAP ALIGN=right>10</TD><TD NOWRAP ALIGN=right>12</TD><TD NOWRAP ALIGN=right>19</TD><TD NOWRAP ALIGN=right>21</TD><TD NOWRAP ALIGN=right>3</TD></TR> <TR><TD NOWRAP ALIGN=right>4</TD><TD NOWRAP ALIGN=right>6</TD><TD NOWRAP ALIGN=right>13</TD><TD NOWRAP ALIGN=right>20</TD><TD NOWRAP ALIGN=right>22</TD></TR> <TR><TD NOWRAP ALIGN=right>23</TD><TD NOWRAP ALIGN=right>5</TD><TD NOWRAP ALIGN=right>7</TD><TD NOWRAP ALIGN=right>14</TD><TD NOWRAP ALIGN=right>16</TD></TR> <TR><TD NOWRAP ALIGN=right>17</TD><TD NOWRAP ALIGN=right>24</TD><TD NOWRAP ALIGN=right>1</TD><TD NOWRAP ALIGN=right>8</TD><TD NOWRAP ALIGN=right>15 </TD></TR></TABLE></TD><TD nowrap> </TD><TD nowrap><FONT FACE=symbol> <BR> <BR> <BR> <BR> <BR> <BR> </FONT> </TD></TR></TABLE></TD><TD ALIGN=center>&nbsp;&nbsp;</TD><TD NOWRAP ALIGN=left> <TABLE CELLSPACING=0 CELLPADDING=0> <TR VALIGN=middle><TD nowrap><FONT FACE=symbol> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> </FONT> </TD><TD nowrap> <TABLE CELLSPACING=2 CELLPADDING=0> <TR><TD NOWRAP ALIGN=right>22</TD><TD NOWRAP ALIGN=right>31</TD><TD NOWRAP ALIGN=right>40</TD><TD NOWRAP ALIGN=right>49</TD><TD NOWRAP ALIGN=right>2</TD><TD NOWRAP ALIGN=right>11</TD><TD NOWRAP ALIGN=right>20</TD></TR> <TR><TD NOWRAP ALIGN=right>21</TD><TD NOWRAP ALIGN=right>23</TD><TD NOWRAP ALIGN=right>32</TD><TD NOWRAP ALIGN=right>41</TD><TD NOWRAP ALIGN=right>43</TD><TD NOWRAP ALIGN=right>3</TD><TD NOWRAP ALIGN=right>12</TD></TR> <TR><TD NOWRAP ALIGN=right>13</TD><TD NOWRAP ALIGN=right>15</TD><TD NOWRAP ALIGN=right>24</TD><TD NOWRAP ALIGN=right>33</TD><TD NOWRAP ALIGN=right>42</TD><TD NOWRAP ALIGN=right>44</TD><TD NOWRAP ALIGN=right>4</TD></TR> <TR><TD NOWRAP ALIGN=right>5</TD><TD NOWRAP ALIGN=right>14</TD><TD NOWRAP ALIGN=right>16</TD><TD NOWRAP ALIGN=right>25</TD><TD NOWRAP ALIGN=right>34</TD><TD NOWRAP ALIGN=right>36</TD><TD NOWRAP ALIGN=right>45</TD></TR> <TR><TD NOWRAP ALIGN=right>46</TD><TD NOWRAP ALIGN=right>6</TD><TD NOWRAP ALIGN=right>8</TD><TD NOWRAP ALIGN=right>17</TD><TD NOWRAP ALIGN=right>26</TD><TD NOWRAP ALIGN=right>35</TD><TD NOWRAP ALIGN=right>37</TD></TR> <TR><TD NOWRAP ALIGN=right>38</TD><TD NOWRAP ALIGN=right>47</TD><TD NOWRAP ALIGN=right>7</TD><TD NOWRAP ALIGN=right>9</TD><TD NOWRAP ALIGN=right>18</TD><TD NOWRAP ALIGN=right>27</TD><TD NOWRAP ALIGN=right>29</TD></TR> <TR><TD NOWRAP ALIGN=right>30</TD><TD NOWRAP ALIGN=right>39</TD><TD NOWRAP ALIGN=right>48</TD><TD NOWRAP ALIGN=right>1</TD><TD NOWRAP ALIGN=right>10</TD><TD NOWRAP ALIGN=right>19</TD><TD NOWRAP ALIGN=right>28 </TD></TR></TABLE></TD><TD nowrap> </TD><TD nowrap><FONT FACE=symbol> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> <BR> </FONT> </TD></TR></TABLE></TD></TR></TABLE></TD><TD nowrap> </TD></TR></TABLE></DIV><BR>  <H5>Exercices</H5> 1- Montrer que les sommes sont bien les mmes, 2- Peut-on en construire d'ordre pair?<BR> <BR> <BR> <BR> <BR> <BR> <A NAME="@default214"></A><A NAME="progJ:carre-magique"></A> <PRE> import java.io.*; import java.lang.*; import java.util.*;  class CarreMagique {    final static int N = 100;   static int     a[][] = new int[N][N];   static int     n;    static void init (int n){      for (int i = 0 ; i &lt; n; ++i)         for (int j = 0; j &lt; n; ++j)             a[i][j] = 0;   }    static void magique (int n) {     int i, j;      i = n - 1; j = n / 2;     for (int k = 1; k &lt;=  n * n; ++k) {         a[i][j] = k;         if ((k % n) == 0)             i = i - 1;         else {             i = (i + 1) % n;              j = (j + 1) % n;         }     }   }    static void erreur (String s) {      System.err.println ("Erreur fatale: " + s);     System.exit (1);   }    static int lire ()  {     int n;      BufferedReader in =          new BufferedReader(new InputStreamReader(System.in));      System.out.print ("Taille du carr magique, svp?::  ");     try {       n = Integer.parseInt (in.readLine());     }     catch (IOException e) {       n = 0;     }     catch (ParseException e) {       n = 0;     }     if ((n &lt;= 0) || (n &gt; N) || (n % 2 == 0))          erreur ("Taille impossible.");     return n;   }    static void imprimer (int n) {      for (int i = 0; i &lt; n; ++i) {         for (int j = 0; j &lt; n; ++j)              System.out.print (leftAligned(5, a[i][j] + " "));         System.out.println ();     }   }    static String leftAligned (int size, String s) {      StringBuffer t = new StringBuffer (s);     for (int i = s.length(); i &lt; size; ++i)         t = t.append(" ");     return new String (t);   }    public static void main (String args[]) {      n = lire();     init(n);       // inutile, mais pdagogique!      magique(n);     imprimer(n);   } } </PRE>  D'abord, on remarque qu'un programme est une suite de directives et de dclarations de classes. Ici, nous n'avons qu'un seule classe <CODE>CarreMagique</CODE>. Auparavant nous avons quelques directives sur un nombre de classes standard dont nous allons nous servir sans utiliser la notation longue (cf plus loin). Chaque classe contient un certain nombre de dclarations de variables et de fonctions ou procdures. (En programmation objet, on parle de <EM>mthodes</EM> au lieu de fonctions ou de procdures. Ici nous utiliserons les deux terminologies). Une des fonctions, conventionnellement de nom <CODE>main</CODE>, est le point de dpart du programme. Ignorons ses arguments pour le moment.<BR> <BR> Dans notre exemple, la fonction <CODE>main</CODE> lit l'entier <I>n</I>  la console, initialise la matrice <I>a</I> avec des zros, puis calcule un carr magique d'ordre <I>n</I> et l'imprime. Nous regardons maintenant les autres fonctions et procdures. Remarquons que les commentaires sont compris entre les sparateurs <CODE>/*</CODE> et <CODE>*/</CODE>, ou aprs <CODE>//</CODE> comme en C++.<BR> <BR> La classe <CODE>CarreMagique</CODE> commence par la dclaration de trois variables. La premire dclaration dfinit une constante <CODE>N</CODE> entire (<EM>integer</EM> en anglais, <CODE>int</CODE> en abrg) qui reprsente la taille maximale du carr autoris. Il est frquent d'crire les constantes avec des majuscules uniquement. Nous adoptons la convention suivante sur les noms: les noms de constantes ou de classes commencent par des majuscules, les noms de variables ou de fonctions commencent par une minuscule. On peut ne pas respecter cette convention, mais cela rendra les programmes moins lisibles. (Pour le moment, nous n'essayons pas de comprendre les mots cls <CODE>final</CODE> ou <CODE>static</CODE> --- ce deuxime mot-cl reviendra trs souvent dans nos programmes).<BR> <BR> Aprs <CODE>N</CODE>, on dclare un tableau <CODE>a</CODE> d'entiers  deux dimensions (la partie crite avant le symbole <CODE>=</CODE>) et on alloue un tableau <I>N</I>  <I>N</I> d'entiers qui sera sa valeur. Cette dclaration peut sembler trs complique, mais les tableaux adoptent la syntaxe des objets (que nous verrons plus tard) et cela permettra d'initialiser les tableaux par d'autres expressions. Remarquons que les bornes du tableau ne font pas partie de la dclaration. Enfin, une troisime dclaration dit qu'on se servira d'une variable entire <CODE>n</CODE>, qui reprsentera l'ordre du carr magique  calculer. <A NAME="@default215"></A><BR> <BR> Ensuite, dans la classe <CODE>CarreMagique</CODE>, nous n'avons plus que des dfinitions de fonctions. Considrons la premire <CODE>init</CODE>, pas vraiment utile, mais intressante puisque trs simple. Le type <CODE>void</CODE> de son rsultat est vide, il est indiqu avant la dclaration de son nom, comme pour les variables ou les tableaux. (En Pascal, on parlerait de procdure). Elle a un seul paramtre entier <CODE>n</CODE> (donc diffrent de la variable globale dfinie auparavant). Cette procdure remet  zro toute la matrice <I>a</I>. Remarquons qu'on crit <CODE>a[i][j]</CODE> pour son lment <I>a</I><SUB><FONT SIZE=2><I>i</I>,<I>j</I></FONT></SUB> (0 <FONT FACE=symbol></FONT> <I>i</I>,<I>j</I> &lt; <I>n</I>), et que le symbole d'affectation est <CODE>=</CODE> comme en C ou en Fortran (l'oprateur = pour le test d'galit s'crit <CODE>==</CODE>). Les tableaux commencent toujours  l'indice 0. Deux boucles imbriques permettent de parcourir la matrice. L'instruction <CODE>for</CODE> a trois clauses: l'initialisation, le test pour continuer  itrer et l'incrmentation  chaque itration. On initialise la variable fraiche <I>i</I>  0, on continue tant que <I>i</I> &lt; <I>n</I>, et on incrmente <I>i</I> de 1  chaque itration (<CODE>++</CODE> et <CODE>--</CODE> sont les symboles d'incrmentation et de dcrmentation).<BR> <BR> Considrons la fonction <CODE>imprimer</CODE>. Elle a la mme structure, sauf que nous imprimons chaque lment sur 5 caractres cadrs  gauche. Les deux fonctions de librairie <CODE>System.out.print</CODE> et <CODE>System.out.println</CODE> permettent d'crire leur paramtre (avec un retour  la ligne dans le cas de la deuxime). Le paramtre est quelconque et peut mme ne pas exister, c'est le cas ici pour <CODE>println</CODE>. Il est trop tt pour expliquer le dtail de <CODE>leftAligned</CODE>, introduit ici pour rendre l'impression plus jolie, et supposons que l'impression est simplement dclenche par<BR> <BR> <PRE>             System.out.print (a[i][j] + " "); </PRE>  Alors, que veut-dire <CODE>a[i][j] + " "</CODE> ?? A gauche de l'oprateur <CODE>+</CODE>, nous avons l'entier <I>a</I><SUB><FONT SIZE=2><I>i</I>,<I>j</I></FONT></SUB> et  droite une chane de caractres!! Il ne s'agit bien sr pas de l'addition sur les entiers, mais de la concatnation des chanes de caractres. Donc <CODE>+</CODE> transforme son argument de gauche dans la chane de caractres qui le reprsente et ajoute au bout la chane <CODE>" "</CODE> contenant un espace blanc. La procdure devient plus claire. On imprime tous les lments <I>a</I><SUB><FONT SIZE=2><I>i</I>,<I>j</I></FONT></SUB> spars par un espace blanc avec un retour  la ligne en fin de ligne du tableau. La fonction complique <CODE>leftAligned</CODE> ne fait que justifier sur 5 caractres cette impression (il n'existe pas d'impression formatte en Java). En conclusion, on constate que l'oprateur <CODE>+</CODE> est <EM>surcharg</EM>, car il a deux sens en Java: l'addition arithmtique, mais aussi la concatnation des chanes de caractres ds qu'un de ses arguments est une chane de caractres. C'est le seul oprateur surcharg (contrairement  C++ qui autorise tous ses oprateurs  tre surchargs).<BR> <BR> <A NAME="E:proc-erreur"></A> La procdure <CODE>erreur</CODE> prend comme argument la chane de caractres <CODE>s</CODE> et l'imprime prcde d'un message insistant sur le cot fatal de l'erreur. Ici encore, on voit l'utilisation de <CODE>+</CODE> pour la concatnation de deux chanes de caractres. Puis, la procdure fait un appel  la fonction systme <CODE>exit</CODE> <A NAME="@default216"></A>qui arrte l'excution du programme avec un code d'erreur (0 voulant dire arrt normal, tout autre valeur un arrt anormal). (Plus tard, nous verrons qu'il y a bien d'autres manires de gnrer un message d'erreur, avec les exceptions ou les erreurs pr-dfinies).<BR> <BR> La fonction <CODE>lire</CODE> qui n'a pas d'arguments retourne un entier lu  la console. La fonction commence par la dclaration d'une variable entire <CODE>n</CODE> qui contiendra le rsultat retourn. Puis, une ligne cryptique ( apprendre par coeur) permet de dire que l'on va faire une lecture (avec tampon)  la console. On imprime un message (sans retour  la ligne) demandant de rentrer la taille voulue pour le carr magique, et on lit par <CODE>readLine</CODE> une chane de caractre entre  la console. Cette chane est convertie en entier par la fonction <CODE>parseInt</CODE> et le tout est rang dans la variable <CODE>n</CODE>. Si une erreur se produit au cours de la lecture, on rcupre cette erreur et on positionne <CODE>n</CODE>  zro. L'instruction <CODE>try</CODE> permet de dlimiter un ensemble d'instruction o on pourra rcuprer une exception par un <CODE>catch</CODE> qui spcifie les exceptions attendues et l'action  tenir compte en consquence. Tous les langages modernes ont un systme d'exceptions, qui permet de sparer le traitement des erreurs du traitement normal d'un groupe d'instructions. Notre fonction <CODE>lire</CODE> finit par tester si 0 <FONT FACE=symbol></FONT> <I>n</I> &lt; <I>N</I> et si <I>n</I> est impair (c'est  dire <I>n</I> mod 2 <FONT FACE=symbol></FONT> 0). Enfin, la fonction retourne de son rsultat.  <A NAME="@default217"></A><BR> <BR> Il ne reste plus qu' considrer le coeur de notre problme, la construction d'un carr magique d'ordre <I>n</I> impair. On remarquera que la procdure est bien courte, et que l'essentiel de notre programme traite des entres-sortie. C'est un phnomne gnral en informatique: l'algorithme est  un endroit trs localis, mais trs critique, d'un ensemble bien plus vaste. On a vu que pour construire le carr, on dmarre sur l'lment <I>a</I><SUB><FONT SIZE=2><I>n</I>, <FONT FACE=symbol></FONT> <I>n</I>/2 <FONT FACE=symbol></FONT> + 1</FONT></SUB>. On y met la valeur 1. On suit une parallle  la premire diagonale (modulo <I>n</I>), en dposant 2, 3, ..., <I>n</I>. Quand l'lment suivant de la matrice est non vide, on revient en arrire et on recommence sur la ligne prcdente, jusqu' remplir tout le tableau. Comme on sait exactement quand on rencontre un lment non vide, c'est  dire quand la valeur range dans la matrice est un multiple de <I>n</I>, la procdure devient remarquablement simple. (Remarque syntaxique: le point-virgule avant le <CODE>else</CODE> ferait hurler tout compilateur Pascal. En Java comme en C, le point-virgule fait partie de l'instruction. Simplement toute <A NAME="@default218"></A><A NAME="@default219"></A>expression suivie de point-virgule devient une instruction. Pour composer plusieurs instructions en squence, on les concatne entre des accolades comme dans la deuxime alternative du <CODE>if</CODE> ou dans l'instruction <CODE>for</CODE>).<BR> <BR> Remarquons que le programme serait plus simple si au lieu de lire <I>n</I> sur la console, on le prenait en arguments de <CODE>main</CODE>. En effet, l'argument de <CODE>main</CODE> est un tableau de chanes de caractres, qui sont les diffrents arguments pour lancer le programme Java sur la ligne de commande. Alors on supprimerait <CODE>lire</CODE> et <CODE>main</CODE> deviendrait:<BR> <BR> <PRE>   public static void main (String args[]) {      if (args.length &lt; 1)         erreur ("Il faut au moins un argument.");     n = Integer.parseInt(args[0]);     init(n);       // inutile, mais pdagogique!      magique(n);     imprimer(n);   } </PRE>  <A NAME="toc53"></A> <H2>A.2&nbsp;&nbsp;Quelques lments de Java</H2> <H3>A.2.1&nbsp;&nbsp;Symboles, sparateurs, identificateurs</H3><A NAME="@default220"></A>Les identificateurs sont des squences de lettres et de chiffres commenant par une lettre. Les identificateurs sont spars par des espaces, des caractres de tabulation, des retours  la ligne ou par des caractres spciaux comme <CODE>+</CODE>, <CODE>-</CODE>, <CODE>*</CODE>. Certains identificateurs ne peuvent tre utiliss pour des noms de variables ou procdures, et sont rservs pour des <EM>mots cls</EM> de la syntaxe, comme <CODE>class</CODE>, <CODE>int</CODE>, <CODE>char</CODE>, <CODE>for</CODE>, <CODE>while</CODE>, ....<BR> <BR>  <H3>A.2.2&nbsp;&nbsp;Types primitifs</H3><A NAME="@default221"></A><A NAME="@default222"></A><A NAME="@default223"></A><A NAME="@default224"></A><A NAME="@default225"></A>Les entiers ont le type <CODE>byte</CODE>, <CODE>short</CODE>, <CODE>int</CODE> ou <CODE>long</CODE>, selon qu'on reprsente ces entiers signs sur 8, 16, 32 ou 64 bits. On utilise principalement <CODE>int</CODE>, car toutes les machines ont des processeurs 32 bits, et bientt 64 bits. Attention: il y a 2 conventions bien spcifiques sur les nombres entiers: les nombres commenant par <CODE>0x</CODE> sont des nombres hexadcimaux. Ainsi <CODE>0xff</CODE> vaut 255. De mme, sur une machine 32 bits, <CODE>0xffffffff</CODE> vaut -1. Les constantes entires longues sont de la forme <CODE>1L</CODE>, <CODE>-2L</CODE>. Les plus petites et plus grandes valeurs des entiers sont <CODE>Integer.MIN_VALUE</CODE> = -2<SUP><FONT SIZE=2>31</FONT></SUP>, <CODE>Integer.MAX_VALUE</CODE> = 2<SUP><FONT SIZE=2>31</FONT></SUP> -1, des entiers longs <CODE>Long.MIN_VALUE</CODE> = -2<SUP><FONT SIZE=2>63</FONT></SUP>, <CODE>Long.MAX_VALUE</CODE> = 2<SUP><FONT SIZE=2>63</FONT></SUP> -1, <CODE>Byte.MIN_VALUE</CODE> = -128, <CODE>Byte.MAX_VALUE</CODE> = 127, etc.<BR> <BR> <A NAME="@default226"></A><A NAME="@default227"></A><A NAME="@default228"></A>Les rels ont le type <CODE>float</CODE> ou <CODE>double</CODE>. Ce sont des nombres flottants en simple ou double prcision. Les constantes sont en notation dcimale <CODE>3.1416</CODE> ou en notation avec exposant <CODE>31.416e-1</CODE> et respectent la norme IEEE 754. Par dfaut les constantes sont prise en double prcision, <CODE>3.1416f</CODE> est un flottant en simple prcision. Les valeurs minimales et maximales sont <CODE>Float.MIN_VALUE</CODE> et <CODE>Float.MAX_VALUE</CODE>. Il existe aussi les constantes de la norme IEEE, <CODE>Float.POSITIVE_INFINITY</CODE>, <CODE>Float.NEGATIVE_INFINITY</CODE>, <CODE>Float.NaN</CODE>, etc.<BR> <BR> <A NAME="@default229"></A><A NAME="@default230"></A><A NAME="@default231"></A><A NAME="@default232"></A>Les boolens ont le type <CODE>boolean</CODE>. Les constantes boolennes sont <CODE>true</CODE> et <CODE>false</CODE>.<BR> <BR> <A NAME="@default233"></A><A NAME="@default234"></A>Les caractres sont de type <CODE>char</CODE>. Les constantes sont crites entre apostrophes, comme <CODE>'A'</CODE>, <CODE>'B'</CODE>, <CODE>'a'</CODE>, <CODE>'b'</CODE>, <CODE>'0'</CODE>, <CODE>'1'</CODE>, <CODE>' '</CODE>. Le caractre apostrophe se note <CODE>'\''</CODE>, et plus gnralement il y a des conventions pour des caractres frquents, <CODE>'\n'</CODE> pour <EM>newline</EM>, <CODE>'\r'</CODE> pour retour-charriot, <CODE>'\t'</CODE> pour tabulation, <CODE>'\\'</CODE> pour <CODE>\</CODE>. Attention: les caractres sont cods sur 16 bits, avec le standard international Unicode. On peut aussi crire un caractre par son code <CODE>'\u0'</CODE> pour le caractre nul (code 0).<BR> <BR> Les constantes chanes de caractres sont crites entre guillemets, comme dans <CODE>"Pierre et Paul"</CODE>. On peut mettre des caractres spciaux  l'intrieur, par exemple <CODE>"Pierre\net\nPaul\n"</CODE> qui s'imprimera sur trois lignes. Pour mettre un guillemet dans une chane, on crit <CODE>\"</CODE>. Si les constantes de type chanes de caractres ont une syntaxe spciale, la classe <CODE>String</CODE> des chnes de caractres n'est pas un type primitif.<BR> <BR> En Java, il n'y a pas de type numr. On utilera des constantes normales pour reprsenter de tels types. Par exemple:<BR> <BR> <PRE> final static int BLEU = 0, BLANC = 1, ROUGE = 2; int c = BLANC; </PRE>   <H3>A.2.3&nbsp;&nbsp;Expressions</H3> <H4>Expressions lmentaires</H4>Les expressions arithmtiques s'crivent comme en mathmatiques. Les oprateurs arithmtiques sont <CODE>+</CODE>, <CODE>-</CODE>, <CODE>*</CODE>, <CODE>/</CODE>, et <CODE>%</CODE> pour modulo. Les oprateurs logiques sont <CODE>&gt;</CODE>, <CODE>&gt;=</CODE>, <CODE>&lt;</CODE>, <CODE>&lt;=</CODE>, <CODE>==</CODE> et <CODE>!=</CODE> pour faire des comparaisons (le dernier signifiant <FONT FACE=symbol></FONT>). Plus intressant, les oprateurs <CODE>&amp;&amp;</CODE> et <CODE>||</CODE> permettent d'valuer de la gauche vers la droite un certain nombre de conditions <A NAME="@default235"></A>(en fait toutes les expressions s'valuent de la gauche vers la droite  la diffrence de C ou de Caml dont l'ordre peut tre laiss  la disposition de l'optimiseur). Une expression logique (encore appele boolenne) peut valoir <CODE>true</CODE> ou <CODE>false</CODE>. La ngation est reprsente par l'oprateur <CODE>!</CODE>. Ainsi<BR> <BR> <PRE> (i &lt; N) &amp;&amp; (a[i] != '\n') &amp;&amp; !exception </PRE>  donnera la valeur <CODE>true</CODE> si <CODE>i</CODE> &lt; <CODE>N</CODE> et si <CODE>a[i]</CODE> <FONT FACE=symbol></FONT> <I>newline</I> et si <CODE>exception</CODE> = <CODE>false</CODE>. Son rsultat sera <CODE>false</CODE> ds que <CODE>i</CODE> <FONT FACE=symbol></FONT> <CODE>N</CODE> sans tester les autres prdicats de cette conjonction, ou alors si <CODE>i</CODE> &lt; <CODE>N</CODE> et <CODE>a[i]</CODE> = newline, .... <BR> <BR>  <H4>Conversions</H4><A NAME="@default236"></A>Il est important de bien comprendre les rgles de conversions implicites dans l'valuation des expressions. Par exemple, si <CODE>f</CODE> est rel, et si <CODE>i</CODE> est entier, l'expression <CODE>f + i</CODE> est un rel qui s'obtient par la conversion implicite de <CODE>i</CODE> vers un <CODE>float</CODE>. Certaines conversions sont interdites, comme par exemple indicer un tableau par un nombre rel. En gnral, on essaie de faire la plus petite conversion permettant de faire l'opration (cf. figure <A HREF="main013.html#fig:conversions-java">A.1</A>). Ainsi un caractre n'est qu'un petit entier. Ce qui permet de faire facilement certaines fonctions comme la fonction qui convertit une chane de caractres ASCII en un entier (<CODE>atoi</CODE> est un raccourci pour <EM>Ascii To Integer</EM>) <A NAME="@default237"></A><BR> <BR> <A NAME="progC:ex-atoi"></A> <PRE> static int atoi (String s) {      int n = 0;      for (int i = 0; i &lt; s.length(); ++i)          n = 10 * n + (s.charAt(i) - '0');      return n; } </PRE>  On peut donc remarquer que <CODE>s.charAt(i) - '0'</CODE> permet de calculer l'entier qui reprsente la diffrence entre le code de <CODE>s.charAt(i)</CODE> et celui de <CODE>'0'</CODE>. N'oublions pas que cette fonction est plus simplement calcule par <CODE>Integer.parseInt(s)</CODE>.<BR> <BR> <BLOCKQUOTE><HR><DIV ALIGN=center><IMG SRC="main062.gif"></DIV> <BR> <BR> <DIV ALIGN=center>Figure A.1&nbsp;: Conversions implicites<A NAME="fig:conversions-java"></A><A NAME="@default238"></A></DIV> <HR></BLOCKQUOTE><A NAME="unsigned-char"></A>Les conversions implicites suivent la figure <A HREF="main013.html#fig:conversions-java">A.1</A>. Pour toute opration, on convertit toujours au le plus petit commun majorant des types des oprandes. Des conversions explicites sont aussi possibles, et recommandes dans le doute. On peut les faire par l'opration de coercion (<EM>cast</EM>) suivante <A NAME="@default239"></A><A NAME="@default240"></A><BR> <BR> <PRE> <CODE>(</CODE><I>type-name</I><CODE>)</CODE><I> expression</I> </PRE>  L'expression est alors convertie dans le type indiqu entre parenthses devant l'expression. L'oprateur <CODE>=</CODE> d'affectation est un oprateur comme les autres dans les expressions. Il subit donc les mmes lois de conversion. Toutefois, il se distingue des autres oprations par le type du rsultat. Pour un oprateur ordinaire, le type du rsultat est le type commun obtenu par conversion des deux oprandes. Pour une affectation, le type du rsultat est le type de l'expression  gauche de l'affectation. Il faut donc faire une conversion explicite sur l'expression de droite pour que le rsultat soit cohrent avec le type de l'expression de gauche. Enfin, dans les appels de fonctions, il y a aussi une opration similaire  une affectation pour passer les arguments, et donc des conversions des arguments sont possibles.<BR> <BR>  <H4>Affectation</H4><A NAME="@default241"></A><A NAME="@default242"></A>Quelques oprateurs sont moins classiques: l'affectation, les oprations d'incrmentation et les oprations sur les <EM>bits</EM>. L'affectation est un oprateur qui rend comme valeur la valeur affecte  la partie gauche. On peut donc crire simplement<BR> <BR> <PRE> x = y = z = 1; </PRE>  pour <BR> <BR> <PRE> x = 1; y = 1; z = 1; </PRE>  Une expression qui contient une affectation modifie donc la valeur d'une variable pendant son valuation. On dit alors que cette expression a un <EM>effet de bord</EM> <A NAME="C:effets-de-bord"></A>. Les effets de bord sont  manipuler avec prcautions, car leur effet peut dpendre d'un ordre d'valuation trs complexe. Il est par exemple peu recommand de mettre plus qu'un effet de bord dans une expression.<BR> <BR>  <H4>Expressions d'incrmentation</H4><A NAME="@default243"></A><A NAME="@default244"></A><A NAME="@default245"></A><A NAME="@default246"></A>D'autres oprations dans les expressions peuvent changer la valeur des variables. Les oprations de pr-incrmentation, de post-incrmentation, de pr-dcrmentation, de post-dcrmentation permettent de donner la valeur d'une variable en l'incrmentant ou la dcrmentant avant ou aprs de lui ajouter ou retrancher 1. Supposons que <CODE>n</CODE> vaille 5, alors le programme suivant<BR> <BR> <PRE> x = ++n; y = n++; z = --n; t = n--; </PRE>  fait passer <CODE>n</CODE>  6, met 6 dans <CODE>x</CODE>, met 6 dans <CODE>y</CODE>, fait passer <CODE>n</CODE>  7, puis retranche 1  <CODE>n</CODE> pour lui donner la valeur 6  nouveau, met cette valeur 6 dans <CODE>z</CODE> et dans <CODE>t</CODE>, et fait passer <CODE>n</CODE>  5. Plus simplement, on peut crire simplement<BR> <BR> <PRE> ++i; j++; </PRE>  pour <BR> <BR> <PRE> i = i + 1; j = j + 1; </PRE>  De manire identique, on pourra crire<BR> <BR> <PRE> if (c != ' ')     c = s.charAt.(i++); </PRE>  pour <BR> <BR> <PRE> if (c != ' ') {     c = s.charAt.(i);     ++i; } </PRE>  En rgle gnrale, il ne faut pas abuser des oprations d'incrmentation. Si c'est une commodit d'criture comme dans les deux cas prcdents, il n'y a pas de problme. Si l'expression devient incomprhensible et peut avoir plusieurs rsultats possibles selon un ordre d'valuation dpendant de l'implmentation, alors il ne faut pas utiliser ces oprations et on doit casser l'expression en plusieurs morceaux pour sparer la partie effet de bord. <A NAME="@default247"></A><BR> <BR> <BLOCKQUOTE> <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1> <TR><TD ALIGN=left><FONT SIZE=4>On ne doit pas faire trop d'effets de bord dans une mme expression</FONT></TD></TR></TABLE> </BLOCKQUOTE> <H4>Expressions sur les bits</H4><A NAME="@default248"></A>Les oprations sur les <EM>bits</EM> peuvent se rvler, elles, trs utiles. On peut faire <CODE>&amp;</CODE> (<EM>et</EM> logique), <CODE>|</CODE> (<EM>ou</EM> logique), <CODE>^</CODE> (<EM>ou</EM> exclusif), <CODE>&lt;&lt;</CODE> (dcalage vers la gauche), <CODE>&gt;&gt;</CODE> (dcalage vers la droite), <CODE>~</CODE> (complment  un). Ainsi<BR> <BR> <PRE> x = x &amp; 0xff; y = y | 0x40; </PRE>  mettent dans <CODE>x</CODE> les 8 derniers bits de <CODE>x</CODE> et positionne le 6<SUP><FONT SIZE=2><FONT SIZE=2>me</FONT></FONT></SUP> bit  partir de la droite dans <CODE>y</CODE>. Il faut bien distinguer les oprations logiques <CODE>&amp;&amp;</CODE> et <CODE>||</CODE>  rsultat boolens 0 ou 1 des oprations <CODE>&amp;</CODE> et <CODE>|</CODE> sur les <EM>bits</EM> qui donnent toute valeur entire. Par exemple, si <CODE>x</CODE> vaut 1 et <CODE>y</CODE> vaut 2, <CODE>x &amp; y</CODE> vaut 0 et <CODE>x &amp;&amp; y</CODE> vaut 1.<BR> <BR> Les oprations <CODE>&lt;&lt;</CODE> et <CODE>&gt;&gt;</CODE> dcalent leur oprande de gauche de la valeur indique par l'oprande de droite. Ainsi <CODE>3 &lt;&lt; 2</CODE> vaut 12, et <CODE>7 &gt;&gt; 2</CODE> vaut 1. Les dcalages  gauche introduisent toujours des zros sur les bits de droite. Pour les bits de gauche dans le cas des dcalages  droite, c'est dpendant de la machine; mais si l'expression dcale est <CODE>unsigned</CODE>, ce sont toujours des zros.<BR> <BR> Le complment  un est trs utile dans les expressions sur les <EM>bits</EM>. Il permet d'crire des expressions indpendantes de la machine. Par exemple<BR> <BR> <PRE> x = x &amp; ~0x7f; </PRE>  remet  zro les 7 bits de gauche de <CODE>x</CODE>, indpendamment du nombre de bits pour reprsenter un entier. Une notation, supposant des entiers sur 32 bits et donc dpendante de la machine, serait<BR> <BR> <PRE> x = x &amp; 0xffff8000; </PRE>   <H4>Autres expressions d'affectation</H4><A NAME="@default249"></A><A NAME="@default250"></A>A titre anecdotique, les oprateurs d'affectation peuvent tre plus complexes que la simple affectation et permettent des abrviations parfois utiles. Ainsi, si <I>op</I> est un des oprateurs <CODE>+</CODE>, <CODE>-</CODE>, <CODE>*</CODE>, <CODE>/</CODE>, <CODE>%</CODE>, <CODE>&lt;&lt;</CODE>, <CODE>&gt;&gt;</CODE>, <CODE>&amp;</CODE>, <CODE>^</CODE>, ou <CODE>|</CODE>,<BR> <BR> <PRE> <I>e</I><SUB><FONT SIZE=2>1</FONT></SUB><I> op</I><CODE>=</CODE><I> e</I><SUB><FONT SIZE=2>2</FONT></SUB> </PRE>  est un raccourci pour<BR> <BR> <PRE> <I>e</I><SUB><FONT SIZE=2>1</FONT></SUB><I> </I><CODE>=</CODE><I> e</I><SUB><FONT SIZE=2>1</FONT></SUB><I> op e</I><SUB><FONT SIZE=2>2</FONT></SUB> </PRE>   <H4>Expressions conditionnelles</H4><A NAME="@default251"></A>Parfois, on peut trouver un peu long d'crire<BR> <BR> <PRE> if (a &gt; b)     z = a; else     z = b; </PRE>  L'expression conditionnelle <BR> <BR> <PRE> <I>e</I><SUB><FONT SIZE=2>1</FONT></SUB><I> </I><CODE>?</CODE><I> e</I><SUB><FONT SIZE=2>2</FONT></SUB><I> </I><CODE>:</CODE><I> e</I><SUB><FONT SIZE=2>3</FONT></SUB><I> </I> </PRE>  value <I>e</I><SUB><FONT SIZE=2>1</FONT></SUB> d'abord. Si non nul, le rsultat est <I>e</I><SUB><FONT SIZE=2>2</FONT></SUB>, sinon <I>e</I><SUB><FONT SIZE=2>3</FONT></SUB>. Donc le maximum de <CODE>a</CODE> et <CODE>b</CODE> peut s'crire<BR> <BR> <PRE> z = (a &gt; b) ? a : b; </PRE>  Les expressions conditionnelles sont des expressions comme les autres et vrifient les lois de conversion. Ainsi si <I>e</I><SUB><FONT SIZE=2>2</FONT></SUB> est flottant et <I>e</I><SUB><FONT SIZE=2>3</FONT></SUB> est entier, le rsultat sera toujours flottant.<BR> <BR>  <H4>Prcdence et ordre d'valuation</H4><A NAME="@default252"></A><A NAME="@default253"></A>Certains oprateurs ont des prcdences videntes, et limitent l'utilisation des parenthses dans les expressions. D'autres sont moins clairs, particulirement en C o leur nombre est plus grand qu'en Pascal. Voici la table donnant les prcdences dans l'ordre dcroissant et le parenthsage en cas d'galit<BR> <BR> <DIV ALIGN=center> <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1> <TR><TD NOWRAP ALIGN=center COLSPAN=3><FONT SIZE=3>Oprateurs</FONT></TD><TD NOWRAP ALIGN=center><FONT SIZE=3>Associativit</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>() [] -&gt; .</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>! ~ ++ -- + - = * &amp; (</FONT></CODE><FONT SIZE=3><I>type</I></FONT><CODE><FONT SIZE=3>) sizeof</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>droite  gauche</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>*   /  %</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>+   -</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>&lt;&lt;  &gt;&gt;</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>&lt;   &lt;=  &gt;  &gt;=</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>==  !=</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>&amp;</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>^</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>|</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>&amp;&amp;</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>||</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>?:</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>droite  gauche</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>= += -= /= %= &amp;= ^= |= &lt;&lt;= &gt;&gt;=</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>droite  gauche</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><CODE><FONT SIZE=3>,</FONT></CODE></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD NOWRAP ALIGN=left><FONT SIZE=3>gauche  droite</FONT></TD></TR> <TR><TD NOWRAP ALIGN=left><FONT SIZE=3></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD><TD ALIGN=center><FONT SIZE=3><FONT SIZE=3>&nbsp;&nbsp;&nbsp;</FONT></FONT></TD></TR></TABLE><FONT SIZE=3> </FONT> </DIV><BR> En rgle gnrale, il est conseill de mettre des parenthses si les prcdences ne sont pas claires. Par exemple<BR> <BR> <PRE> if ((x &amp; MASK) == 0) ... </PRE>   <H3>A.2.4&nbsp;&nbsp;Instructions</H3>Toute expression suivie d'un point-virgule devient une instruction. Ainsi <A NAME="@default254"></A><A NAME="@default255"></A><BR> <BR> <PRE> x = 3; ++i; System.out.print(...); </PRE>  sont des instructions (une expression d'affectation, d'incrmentation, un appel de fonction suivi de point-virgule). Donc point-virgule fait partie de l'instruction, et n'est pas un sparateur comme en Pascal. De mme, les accolades <CODE>{</CODE> <CODE>}</CODE> permettent de regrouper des instructions en squence. Ce qui permet de mettre plusieurs instructions dans les alternatives d'un <CODE>if</CODE> par exemple.<BR> <BR> Les instructions de contrle sont  peu prs les mmes qu'en Pascal. D'abord les instructions conditionnelles <CODE>if</CODE> sont de la forme <A NAME="@default256"></A><BR> <BR> <PRE> if (<I>E</I>)     <I>S</I><SUB><FONT SIZE=2>1</FONT></SUB> </PRE>  ou<BR> <BR> <PRE> if (<I>E</I>)     <I>S</I><SUB><FONT SIZE=2>1</FONT></SUB> else     <I>S</I><SUB><FONT SIZE=2>2</FONT></SUB> </PRE>  Remarquons bien qu'une instruction peut tre une expression suivie d'un point-virgule (contrairement  Pascal). Donc l'instruction suivante est compltement licite<BR> <BR> <PRE> if (x &lt; 10)     c = '0' + x; else     c = 'a' + x - 10; </PRE>  Il y a la mme convention qu'en Pascal pour les <CODE>if</CODE> embots. Le <CODE>else</CODE> se rapportant toujours au <CODE>if</CODE> le plus proche. Une srie de <CODE>if</CODE> peut tre remplace par une instruction de slection par cas, c'est l'instruction <CODE>switch</CODE>. Elle a la syntaxe suivante <A NAME="@default257"></A><BR> <BR> <PRE> switch (<I>E</I>) {     case <I>c</I><SUB><FONT SIZE=2>1</FONT></SUB>: <I>instructions</I>     case <I>c</I><SUB><FONT SIZE=2>2</FONT></SUB>: <I>instructions</I>     ...     case <I>c</I><SUB><FONT SIZE=2><I>n</I></FONT></SUB>: <I>instructions</I>     default: <I>instructions</I> } </PRE>  Cette instruction a une idiosyncrasie bien particulire. Pour sortir de l'instruction, il faut excuter une instruction <CODE>break</CODE>. Sinon, le reste de l'instruction est fait en squence. Cela permet de regrouper plusieurs alternatives, mais peut tre particulirement dangereux. Par exemple, le programme suivant <A NAME="@default258"></A><BR> <BR> <PRE> switch (c) {     case '\t':      case ' ':         ++ nEspaces;         break;     case '0': case '1': case '2': case '3': case '4':      case '5': case '6': case '7': case '8': case '9':          ++ nChiffres;         break;     default:         ++ nAutres;         break; } </PRE>  permet de factoriser le traitement de quelques cas. On verra que l'instruction <CODE>break</CODE> permet aussi de sortir des boucles. Il faudra donc bien faire attention  ne pas oublier le <CODE>break</CODE>  la fin de chaque cas, et  ce que <CODE>break</CODE> ne soit pas intercept par une autre instruction.<BR> <BR> Les itrations sont ralises par les instructions <CODE>for</CODE>, <CODE>while</CODE>, et <CODE>do...while</CODE>. L'instruction <CODE>while</CODE> permet d'itrer tant qu'une expression boolenne est vraie, on itre l'instruction <I>S</I> tant que la condition <I>E</I> est vraie par  <A NAME="@default259"></A><BR> <BR> <PRE> while (<I>E</I>)      <I>S</I> </PRE>  et on fait de mme en effectuant au moins une fois la boucle par <A NAME="@default260"></A><BR> <BR> <PRE> do      <I>S</I> while (<I>E</I>); </PRE>  L'instruction d'itration la plus puissante est l'instruction <CODE>for</CODE>. Sa syntaxe est <A NAME="@default261"></A><BR> <BR> <PRE> for (<I>E</I><SUB><FONT SIZE=2>1</FONT></SUB>; <I>E</I><SUB><FONT SIZE=2>2</FONT></SUB>; <I>E</I><SUB><FONT SIZE=2>3</FONT></SUB>)     <I>S</I> </PRE>  qui est quivalente  <BR> <BR> <PRE> <I>E</I><SUB><FONT SIZE=2>1</FONT></SUB>; while (<I>E</I><SUB><FONT SIZE=2>2</FONT></SUB>) {      <I>S</I>;      <I>E</I><SUB><FONT SIZE=2>3</FONT></SUB>; } </PRE>  Elle est donc beaucoup plus complexe qu'en Pascal ou Caml et peut donc ne pas terminer, puisque les expressions <I>E</I><SUB><FONT SIZE=2>2</FONT></SUB> et <I>E</I><SUB><FONT SIZE=2>3</FONT></SUB> sont quelconques. On peut toujours crire des itrations simples:<BR> <BR> <PRE> for (i = 0; i &lt; 100; ++i)      a[i] = 0; </PRE>  mais l'itration suivante est plus complexe (voir page <A HREF="main005.html#progC:recherche-hachage-1">X</A>)<BR> <BR> <PRE> for (int i = h(x); i != -1; i = col[i])      if (x.equals(nom[i]))         return tel[i]; </PRE>  Nous avons vu que l'instruction <CODE>break</CODE> permet de sortir d'une instruction <CODE>switch</CODE>, mais aussi de toute instruction d'itration. De mme, l'instruction <CODE>continue</CODE> permet de passer brusquement  l'itration suivante. Ainsi<BR> <BR> <PRE> for (i = 0; i &lt; n; ++i) {     if (a[i] &lt; 0)         continue;     ... } </PRE>  <A NAME="@default262"></A>C'est bien commode quand le cas <I>a</I><SUB><FONT SIZE=2><I>i</I></FONT></SUB> <FONT FACE=symbol></FONT> 0 est trs long. Les <CODE>break</CODE> et <CODE>continue</CODE> peuvent prciser l'tiquette de l'itration qu'elles rfrencent. Ainsi, dans l'exemple suivant, on dclare une tiquette devant l'instruction <CODE>while</CODE>, et on sort des deux itrations comme suit:<BR> <BR> <PRE> boucle:   while (<I>E</I>) {     for (i = 0; i &lt; n; ++i) {       if (a[i] &lt; 0)           break boucle;       ...     }   } </PRE>  Finalement, il n'y a pas d'instruction <CODE>goto</CODE>. Il y a toutefois des exceptions que nous verrons plus tard.<BR> <BR>  <H3>A.2.5&nbsp;&nbsp;Procdures et fonctions</H3><A NAME="@default263"></A><A NAME="@default264"></A>La syntaxe des fonctions et procdures a dj t vue dans l'exemple du carr magique. Chaque classe contient une suite linaire de fonctions ou procdures, non embotes. Par convention, le dbut de l'excution est donn  la procdure publique <CODE>main</CODE> qui prend un tableau de chanes de caractres comme argument. Pour dclarer une fonction, on dclare d'abord sa signature, c'est  dire le type de son rsultat et des arguments, puis son corps, c'est  dire la suite d'instructions qui la ralisent entre accolades. Ainsi dans<BR> <BR> <PRE> static int suivant (int x) {   if (x % 2 == 1)        return 3 * x + 1;   else       return x / 2; } </PRE>  le rsultat est de type entier ( cause du mot-cl <CODE>int</CODE> avant <CODE>suivant</CODE>) et l'unique argument <I>x</I> est aussi entier. L'instruction<BR> <BR> <PRE> return <I>e</I>; </PRE>  <A NAME="@default265"></A><A NAME="@default266"></A>sort de la fonction en donnant le rsultat <I>e</I>, et permet de  rendre un rsultat  la fonction. Dans les deux fonctions qui suivent, le rsultat est vide, donc de type <CODE>void</CODE> et l'argument est entier.<BR> <BR> <PRE> static void test (int x) {   while (x != 1)        x = suivant (x); }  static void testConjecture (int n) {   for (int x=1; x &lt;= n; ++x) {       test (x);       System.out.println (x);   } } </PRE>  On calcule donc les itrations de la fonction qui renvoie 3<I>x</I>+1 si <I>x</I> est impair, et <FONT FACE=symbol></FONT> <I>x</I>/2 <FONT FACE=symbol></FONT> sinon. (En fait, on ne sait pas dmontrer qu'on finit toujours avec 1 pour tout entier <I>x</I> de dpart. Par exemple,  partir de 7, on obtient 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1). <BR> <BR> <A NAME="@default267"></A><A NAME="@default268"></A>Il peut y avoir des variables locales dans une procdure, plus exactement dans toute instruction compose entoure par des accolades. Les variables globales sont elles dclares au mme niveau que les procdures ou fonctions. Les variables locales peuvent tre initialises. Cela revient  faire la dclaration et l'affectation par la valeur initiale, qui peut tre une expression complexe et qui est value  chaque entre dans la fonction. Les variables locales disparaissent donc quand on quitte la fonction.<BR> <BR> Dans une fonction, on peut accder aux variables globales et ventuellement les modifier, quoiqu'il est recommand de ne pas faire trop d'effets de bord, mais on ne pourra passer une variable en argument pour modifier sa valeur. Prenons l'exemple de la fonction <CODE>suivant</CODE> prcdente, on a chang la valeur du paramtre <I>x</I> dans le corps de la fonction. Mais ceci n'est vrai qu' l'intrieur du corps de la fonction. En Java, seule la valeur du paramtre compte, on ne modifiera donc pas ainsi une variable extrieure  la fonction, passe en paramtre.<BR> <BR> <BLOCKQUOTE> <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1> <TR><TD ALIGN=left><FONT SIZE=4>Les paramtres des fonctions sont passs par valeur</FONT></TD></TR></TABLE> </BLOCKQUOTE> <H3>A.2.6&nbsp;&nbsp;Classes</H3><A NAME="@default269"></A><A NAME="@default270"></A>Une classe est  la fois la dclaration d'un type non primitif et d'une srie de fonctions ou procdures associs. L'ide est de dcouper en petits modules l'espace des donnes et des fonctions. Les lments de l'ensemble reprsent par une classe sont les objets. Dans une classe, il y a une partie champs de donnes, et une autre qui est un ensemble de fonctions ou procdures. Dans la programmation oriente-objet, on aime parler d'objets comme des intances d'une classe, et de mthodes pour les fonctions et procdures associes (``mthodes'' car ce sont souvent des mthodes d'accs aux objets de la classe que ralisent ces fonctions). Bien sr, il peut y avoir des classes sans donnes ou sans mthodes. Prenons le cas d'une structure d'enregistrement classique en Pascal ou en C. On peut crire:<BR> <BR> <A NAME="@default271"></A><PRE> class Date {   int         j;   /* Jour */   int         m;   /* Mois */   int         a;   /* Anne */ }; </PRE>  et par la suite on peut dclarer des variables, comme on le faisait avec les variables de type primitif (entier, rel, caractre ou boolen). Ainsi on note deux dates importantes<BR> <BR> <PRE> static final int Jan=1, Fev=2, Mar=3, Avr=4, Mai=5, Juin=6,          Juil=7, Aou=8, Sep=9, Oct=10, Nov=11, Dec=12;  Date bastille = new Date(), berlin = new Date();  bastille.j = 14; bastille.m = Juil; bastille.a = 1789; berlin.j = 10; berlin.m = Nov; berlin.a = 1989; </PRE>  Nous venons de dfinir deux objets <CODE>bastille</CODE> et <CODE>berlin</CODE>, et pour accder  leurs champs on utilise la notation bien connue suffixe avec un point. Le champ jour de la date de la prise de la Bastille s'obtient donc par <CODE>bastille.j</CODE>. Rien de neuf, c'est la notation utilise en Pascal, en C, ou en Caml. Pour crer un objet, on utilise le mot-cl <CODE>new</CODE> suivi du nom de la classe et de parenthses. (Pour les experts, les objets sont reprsents par un pointeur et leur contenu se trouve dans le tas). Un objet non initialis vaut <CODE>null</CODE>. <BR> <BR> Nos dates sont un peu lourdes  manipuler. Trs souvent, on veut une mthode paramtre pour construire un objet d'une classe. C'est tellement frquent qu'il y a une syntaxe particulire pour le faire. Ainsi si on crit<BR> <BR> <PRE> class Date {   int         j;   /* Jour */   int         m;   /* Mois */   int         a;   /* Anne */    Date (int jour, int mois, int annee) {      this.j = jour;      this.m = mois;      this.a = annee; }; </PRE> <A NAME="@default272"></A>on pourra crer les dates simplement avec<BR> <BR> <PRE>   static Date berlin = new Date(10, Nov, 1989),                bastille = new Date(14, Juil, 1789); </PRE>  Un constructeur est donc une mthode (non statique) sans nom. On indique le type de son rsutat (ie le nom de la classe o il se trouve) et ses paramtres. Le corps de la fonction est quelconque, mais on ne retourne pas explicitement de valeur, puisque son rsultat est toujours l'objet en cours de cration. Le constructeur est utilis derrire un mot-cl <CODE>new</CODE>. Dans le cas o il n'y a pas de constructeur explicite, le constructeur par dfaut (sans arguments) rserve juste l'espace mmoire ncessaire pour l'objet construit. Remarquons que dans le constructeur, on a utilis le mot-cl <CODE>this</CODE> qui dsigne l'objet en cours de cration pour bien comprendre que <CODE>j</CODE>, <CODE>m</CODE> et <CODE>a</CODE> sont des champs de l'objet construit. Le constructeur se finit donc implicitement par <CODE>return this</CODE>. Mais, ce mot-cl n'tait pas vraiment utile. On aurait pu simplement crire<BR> <BR> <PRE> class Date {   int         j;   /* Jour */   int         m;   /* Mois */   int         a;   /* Anne */    Date (int jour, int mois, int annee) {      j = jour;      m = mois;      a = annee; }; </PRE>  Un champ peut tre dclar statique. Cela signifie qu'il n'existe qu' un seul exemplaire dans la classe dont il fait partie. Une donne statique est donc attache  une classe et non aux objets de cette classe. Supposons par exemple que l'origine des temps (pour le systme Unix) soit une valeur de premire importance, ou que nous voulions compter le nombre de dates cres avec notre constructeur. On crirait:<BR> <BR> <PRE> class Date {   int         j;   /* Jour */   int         m;   /* Mois */   int         a;   /* Anne */    static final int Jan=1, Fev=2, Mar=3, Avr=4, Mai=5, Juin=6,          Juil=7, Aou=8, Sep=9, Oct=10, Nov=11, Dec=12;    static Date tempsZeroUnix = new Date (1, Jan, 1970);   static int nbInstances = 0;    Date (int jour, int mois, int annee) {      j = jour;      m = mois;      a = annee;      ++ nbInstances; }; </PRE>  Il y a donc deux sortes de donnes dans une classe, les champs associs  chaque instance d'un objet (ici les jours, mois et annes), et les champs uniques pour toute la classe (ici les constantes, la date temps-zro pour Unxi et le nombre d'utilisateurs). Les variables statiques sont initialises au chargement de la classe, les autres dynamiquement en accdant aux champs de l'objet.<BR> <BR> Considrons maintenant les mthodes d'une classe. A nouveau, elles sont de deux sortes: les mthodes dynamiques et les mthodes statiques. Dans notre cours, nous avons fortement privilgi cette deuxime catgorie, car leur utilisation est trs proche de celle des fonctions ou procdures de C ou de Pascal. Les mthodes statiques sont prcdes du mot-cl <CODE>static</CODE>, les mthodes dynamiques n'ont pas de prfixe. La syntaxe est celle d'une fonction usuelle. Prenons le cas de l'impression de notre classe Date.<BR> <BR> <PRE> class Date {   ...   static void imprimer (Date d) {       System.out.print ("d = " + d.j + ", " +                         "m = " + d.m + ", " +                         "a = " + d.a);   } } </PRE>  et on pourra imprimer avec des instructions du genre<BR> <BR> <PRE>   Date.imprimer (berlin);   Date.imprimer (bastille); </PRE>  Remarquons qu'on doit qualifier le nom de procdure par le nom de la classe, si on se trouve dans une autre classe. (Cette syntaxe est cohrente avec celle des accs aux champs de donnes). Dans les langages de programmation usuels, on retrouve cette notation aussi pour accder aux fonctions de modules diffrents. On peut aussi crire de mme une fonction qui teste l'galit de deux dates<BR> <BR> <PRE> class Date {   ...   static boolean equals (Date d1, Date d2) {       return d1.j == d2.j &amp;&amp; d1.m == d2.m &amp;&amp; d1.a == d2.a;   } } </PRE>  Jusqu' prsent, nous avions considr des objets, des fonctions, et des classes. Les mthodes non statiques sont le baba de la programmation objet. Quelle est l'ide? Comme une classe, un objet a non seulement des champs de donnes, mais il contient aussi un vecteur de mthodes. Pour dclencher une mthode, on passe les paramtres aux mthodes de l'objet. Ces fonctions ont la mme syntaxe que les mthodes dynamiques,  une exception prs: elles ont aussi le paramtre implicite <CODE>this</CODE> qui est l'objet dont elles sont la mthode. (Pour accder aux champs de l'objet, <CODE>this</CODE> est facultatif). Ce changement, qui rend plus proches les fonctions et les donnes, peut paratre mineur, mais il est  la base de la programmation objet, car il se combinera  la notion de sous-classe. Prenons l'exemple des deux mthodes statiques crites prcdemment. Nous pouvons les rcrire non statiquement comme suit:<BR> <BR> <PRE> class Date {   ...   void print () {       System.out.print ("d = " + this.j + ", " +                         "m = " + this.m + ", " +                         "a = " + this.a);   }    boolean equals (Date d) {       return this.j == d.j &amp;&amp; this.m == d.m &amp;&amp; this.a == d.a;   } } </PRE>  ou encore sans le mot-cl <CODE>this</CODE> non ncessaire ici:<BR> <BR> <PRE> class Date {   ...   void print () {       System.out.print ("d = " + j + ", " +                         "m = " + m + ", " +                         "a = " + a);   }    boolean equals (Date d) {       return j == d.j &amp;&amp; m == d.m &amp;&amp; a == d.a;   } } </PRE>  et on pourra indistinctement crire<BR> <BR> <PRE> if (!Date.equals(berlin, bastille))   Date.imprimer (berlin); </PRE>  o<BR> <BR> <PRE> if (!berlin.equals(bastille))   berlin.print (); </PRE>  Dans la deuxime criture, on passe l'argument (quand il existe)  la mthode correspondante de l'objet auquel appartient cette mthode. Nous avons dj utilis cette notation avec les fonctions prdfinies de la librairie. Par exemple <CODE>println</CODE> est une mthode associ au flux de sortie <CODE>out</CODE>, qui lui mme est une donne statique de la classe <CODE>System</CODE>. De mme pour les chanes de caractres: la classe <CODE>String</CODE> dfinit les mthodes <CODE>length</CODE>, <CODE>charAt</CODE> pour obtenir la longueur de l'objet chane <CODE>s</CODE> ou lire le caractre  la position <I>i</I> dans <CODE>s</CODE> comme suit:<BR> <BR> <PRE> String s = "Oh, la belle chane";  if (s.length() &gt; 20)   System.out.println (s.charAt(i)); </PRE>  Il faut savoir que la mthode (publique) spciale <CODE>toString</CODE> peut tre pris en compte par le systme d'criture standard. Ainsi, dans le cas des dates, si on avait dclar,<BR> <BR> <PRE> class Date {   ...   public String toString () {       return ("d = " + j + ", " +               "m = " + m + ", " +               "a = " + a);   } } </PRE>  on aurait pu seulement crire <BR> <BR> <PRE> if (!berlin.equals(bastille))   System.out.println (berlin); </PRE>  Enfin, dans une classe, on peut directement mettre entre accolades des instructions, ventuellement prcdes par le mot-cl <CODE>static</CODE> pour initialiser divers champs  chaque cration d'un objet ou au chargement de la classe.<BR> <BR> Faisons trois remarques supplmentaires sur les objets. Primo, un objet peut tre pass comme paramtre d'une procdure, mais alors seule la rfrence  l'objet est passe. Il n'y a pas de copie de l'objet. Donc, on peut ventuellement modifier le contenu de l'objet dans la procdure. (Pour copier un objet, on peut souvent utiliser la mthode <CODE>clone</CODE>).  <A NAME="@default273"></A><A NAME="@default274"></A><BR> <BR> <BLOCKQUOTE> <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1> <TR><TD ALIGN=left><FONT SIZE=4>Les objets ne sont jamais copis implicitement</FONT></TD></TR></TABLE> </BLOCKQUOTE>Deuximement, il n'y a pas d'instruction pour dtruire des objets. Ce n'est pas grave, car le <EM>garbage collector</EM> (GC) rcupre automatiquement l'espace mmoire des objets non utiliss. Cela est fait rgulirement, notamment quand il n'y a plus de place en mmoire. C'est un service de rcupration des ordures, comme dans la vie courante. Il n'y a donc pas  se soucier de la d-allocation des objets. Troisimement, il est possible de surcharger les mthodes en faisant varier le type de leurs arguments ou leur nombre. Nous avons dj vu le cas de <CODE>println</CODE> qui prenait zro arguments ou un argument de type quelconque (qui tait en fait transform en chane de caractres avec la mthode <CODE>toString</CODE>). On peut dclarer trs simplement de telles mthodes surcharges, par exemple dans le cas des constructeurs: <A NAME="@default275"></A><BR> <BR> <PRE> class Date {   int         j;   /* Jour */   int         m;   /* Mois */   int         a;   /* Anne */    Date (int jour, int mois, int annee) {       j = jour; m = mois; a = annee;    Date (long n) {       // Un savant calcul du jour, mois et anne  partir du nombre       // de millisecondes depuis l'origine des temps informatiques, ie       // le 1 janvier 1970.   }    Date () {       // idem avec le temps courant <CODE>System.currentTimeMillis</CODE>   } }; </PRE>  Le constructeur adquat sera appel en fonction du type ou du nombre de ses arguments, ici avec trois entiers dsignant les jour, mois et anne, ou avec un seul entier long donnant le nombre de milisecondes depuis le dbut des temps informatiques, ou sans argument pour avoir la date du jour courant. (Remarque: compter le temps avec des milisecondes sur 64 bits reporte le problme du <EM>bug</EM> de l'an 2000  l'an 10<SUP><FONT SIZE=2>8</FONT></SUP>, mais ce n'est pas le cas dans certains systmes Unix o le nombre de secondes sur 32 bits depuis 1970 reporte le problme  l'an 2038!). Il faut faire attention aux abus de surcharge, et introduire une certaine logique dans son utilisation, sinon les programmes deviennent rapidement incomprhensibles. Pire, cela peut tre redoutable lorsqu'on combine surcharge et hritage (cf.&nbsp; plus loin). <BR> <BR> <BLOCKQUOTE> <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1> <TR><TD ALIGN=left><FONT SIZE=4>La surcharge est rsolue statiquement  la compilation.</FONT></TD></TR></TABLE> </BLOCKQUOTE> <H3>A.2.7&nbsp;&nbsp;Sous-classes</H3><A NAME="@default276"></A>Le cours n'utilise pratiquement pas la notion de sous-classe, car cette notion intervient surtout si on fait de la programmation oriente-objet. Nous mentionnons toutefois brivement cette notion. Une classe peut tendre une autre classe. Par exemple, la classe des dates pourrait tre refaite en deux systmes de dates: grgorien ou rvolutionnaire en fonction du nombre de millisecondes (ventuellement ngatif) depuis l'origine des temps informatiques; ou bien une classe tend une classe standard dj fournie comme celle des <EM>applets</EM> pour programmer un navigateur, ou la classe MacLib pour faire le graphique lmentaire de ce cours; etc. Prenons l'exemple ultra classique de la classe des points ventuellement colors, exemple qui a l'avantage d'tre court et suffisant pour expliquer la problmatique rencontre. Un point est reprsent par la paire (<I>x</I>,<I>y</I>) de ses coordonnes<BR> <BR> <PRE> class Point {     int x, y;      Point (int x0, int y0) {     x = x0; y = y0;   }      public String toString () {     return "(" + x + ", " + y +")";   }    void move (int dx, int dy) {     x = x + dx;      y = y + dy;   } } </PRE>  On considre deux mthodes pour convertir un point en chane de caractres (pour l'impression) et une autre <CODE>move</CODE> pour bouger un point, cette dernire mthode tant une procdure qui renvoie donc le type vide. On peut utiliser des objets de cette classe en crivant des instructions de la forme<BR> <BR> <PRE>  Point p = new Point(1, 2);  System.out.println (p);  p.move (-1, -1);  System.out.println (p); </PRE>  Dfinissons  prsent la classe des points colors avec un champ supplmentaire <CODE>couleur</CODE>, en la dclarant comme une extension, ou encore une <EM>sous-classe</EM>, de la classe des points, comme suit:<BR> <BR> <PRE> class PointAvecCouleur extends Point {   int couleur;    PointAvecCouleur (int x0, int y0, int c) {     super (x0, y0); couleur = c;   }      public String toString () {     return "(" + x + ", " + y + ", " + couleur + ")";   } } </PRE> <A NAME="@default277"></A>Les champs <I>x</I> et <I>y</I> de l'ancienne classe des points existent toujours. Le champ couleur est juste ajout. S'il existait dj un champ couleur dans la classe <EM>Point</EM>, on ne ferait que le cacher et l'ancien champ serait toujours accessible par <CODE>super.couleur</CODE> grce au mot-cl <CODE>super</CODE>. Dans la nouvelle classe, nous avons un constructeur qui prend un argument supplmentaire pour la couleur. Ce constructeur doit toujours commencer par un appel  un constructeur de la super-classe (la classe des points). Si on ne met pas d'appel explicite  un constructeur de cette classe, l'instruction <CODE>super()</CODE> est faite implicitement, et ce constructeur doit alors exister dans la super classe. Enfin, la mthode <CODE>toString</CODE> est redfinie pour prendre en compte le nouveau champ pour la couleur. On utilise les points colors comme suit<BR> <BR> <PRE> PointAvecCouleur q = new PointAvecCouleur (3, 4, 0xfff); System.out.println (q); q.move(10,-1); System.out.println (q); </PRE>  La classe des points colors a donc <EM>hrit</EM> des champs <I>x</I> et <I>y</I> et de la mthode <CODE>move</CODE> de la classe des points, mais la mthode <CODE>toString</CODE> a t redfinie. On n'a eu donc qu' programmer l'incrment entre les points normaux et les points colors. C'est le principe de base de la programmation objet: le contrle des programmes est dirig par les donnes et leurs modifications. Dans la programmation classique, on doit changer le corps de beaucoup de fonctions ou de procdures si on change les dclarations des donnes, car la description d'un programme est donn par sa fonctionalit.<BR> <BR> Une mthode ne peut redfinir qu'une mthode de mme type pour ses paramtres et rsultat. Plus exactement, elle peut redfinir une mthode d'une classe plus gnrale dont les arguments ont un type plus gnral. Il est interdit de dfinir les mthodes prfixes par le mot-cl <CODE>final</CODE>. On ne peut non plus donner des modificateurs d'accs plus restrictifs, une mthode publique devant rester publique. Une classe hrite d'une seule classe (hritage simple). Des langages comme Smalltalk ou C++ autorisent l'hritage multiple  partir de plusieurs classes, mais les mthodes sont alors un peu plus dlicates  implmenter. L'hritage est bien sr transitif. D'ailleurs toutes les classes Java hritent d'une unique classe <CODE>Object</CODE>.<BR> <BR> Il se pose donc le problme de savoir quelle mthode est utilise pour un objet donn. C'est toujours la mthode la plus prcise qui peut s'appliquer  l'objet et  ses arguments qui est slectionne. Remarquons que ceci n'est pas forcment dans le corps du programme charg au moment de la rfrence, puisqu'une nouvelle classe peut tre charge, et contenir la mthode qui sera utilise.<BR> <BR> <BLOCKQUOTE> <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1> <TR><TD ALIGN=left><FONT SIZE=4>La rsolution des mthodes dynamiques est faite  l'excution.</FONT></TD></TR></TABLE> </BLOCKQUOTE>Enfin, il y a une faon de convertir un objet en objet d'une super-classe ou d'une sous-classe avec la notation dex conversion explicites (dja vu pour le cas des valeurs numriques). Par exemple<BR> <BR> <PRE> Point p = new Point (10, 10); PointAvecCouleur q = new PointAvecCouleur (20, 20, ROUGE); Point p1 = q; PointAvecCouleur q1 = (PointAvecCouleur) p; PointAvecCouleur q2 = (PointAvecCouleur) p1; </PRE>  Aller vers une classe plus gnrale ne pose pas en gnral de difficults, et le faire explicitement peut forcer la rsolution des surcharges de nom de fonctions, mais l'objet reste le mme. Si on convertit vers une sous-classe plus restrictive, la machine virtuelle Java vrifie  l'excution et peut lever l'exception <CODE>ClassCastException</CODE>. Dans l'exemple prcdent seule l'avant-dernire ligne lvera cette exception.<BR> <BR>  <H3>A.2.8&nbsp;&nbsp;Tableaux</H3><A NAME="@default278"></A>Les tableaux sont des objets comme les autres. Un champ <CODE>length</CODE> indique leur longueur. L'accs aux lments du tableau <I>a</I> s'crit avec des crochets, <CODE>a[i-1]</CODE> reprsente <I>i</I>-me lment. Les tableaux n'ont qu'une seule dimension, un tableau  deux dimensions est considr comme un tableau dont tous les lments sont des tableaux  une dimension, etc. Si on accde en dehors du tableau, une exception est leve. La cration d'un tableau se fait avec le mot-cl <CODE>new</CODE> comme pour les objets, mais il existe une facilit syntaxique pour crer des tableaux  plusieurs dimensions. Voici par exemple le calcul de la table de vrit de l'union de deux oprateurs boolens:<BR> <BR> <PRE> static boolean[][] union (boolean a[][], boolean b[][]) {   boolean c[][] = new boolean [2][2];   for (int i = 0; i &lt; 2; ++i)     for (int j = 0; j &lt; 2; ++j)         c[i][j] = a[i][j] || b[i][j];   return c; } </PRE>  Pour initialiser un tableau, on peut le faire avec des constantes litrales: <BR> <BR> <PRE> boolean intersection [][] = {{true, false},{false, false}}; boolean ouExclusif [][] = {{false, true},{true, false}}; </PRE>  Enfin, on peut affecter des objets d'une sous-classe dans un tableau d'lments d'une classe plus gnrale.<BR> <BR>  <H3>A.2.9&nbsp;&nbsp;Exceptions</H3>Les exceptions sont des objets de toute sous-classe de la classe <CODE>Exception</CODE>. Il existe aussi une classe <CODE>Error</CODE> moins utilise pour les erreurs systme. Toutes les deux sont des sous-classes de la classe <CODE>Throwable</CODE>, dont tous les objets peuvent tre appliqus  l'oprateur <CODE>throw</CODE>, comme suit: <A NAME="@default279"></A><BR> <BR> <PRE> throw <I>e</I>; </PRE>  Ainsi on peut crire en se servant de deux constructeurs de la classe <CODE>Exception</CODE>:<BR> <BR> <PRE> throw new Exception(); throw new Exception ("Accs interdit dans un tableau"); </PRE>  Heureusement, dans les classes des librairies standard, beaucoup d'exceptions sont dja pr-dfinies, par exemple <CODE>IndexOutOfBoundsExeption</CODE>. On rcupre une exception par l'instruction <CODE>try</CODE> ...<CODE>catch</CODE>. Par exemple <A NAME="@default280"></A><A NAME="@default281"></A><BR> <BR> <PRE> try {   // un programme compliqu } catch ( IOException e) {   // essayer de rparer cette erreur d'entre/sortie } catch ( Exception e) {   // essayer de rparer cette erreur plus gnrale } </PRE>  Si on veut faire un traitement uniforme en fin de l'instruction <CODE>try</CODE>, que l'on passe ou non par une exception, que le contrle sorte ou non de l'instruction par une rupture de squence comme un <CODE>return</CODE>, <CODE>break</CODE>, etc, on crit<BR> <BR> <PRE> try {   // un programme compliqu } catch ( IOException e) {   // essayer de rparer cette erreur d'entre/sortie } catch ( Exception e) {   // essayer de rparer cette erreur plus gnrale } finally {   // un peu de nettoyage } </PRE> <A NAME="@default282"></A>Il y a deux types d'exceptions. On doit dclarer les <EM>exceptions vrifies</EM> derrire le mot-cl <CODE>throws</CODE> dans la signature des fonctions qui les lvent. Ce n'est pas la peine pour les <EM>exceptions non vrifies</EM> qui se reconnaissent en appartenant  une sous-classe de la classe <CODE>RuntimeException</CODE>. Ainsi <A NAME="@default283"></A><BR> <BR> <PRE> static int lire () throws IOException, ParseException {   int n;    BufferedReader in =        new BufferedReader(new InputStreamReader(System.in));    System.out.print ("Taille du carr magique, svp?::  ");   n = Integer.parseInt (in.readLine());   if ((n &lt;= 0) || (n &gt; N) || (n % 2 == 0))        erreur ("Taille impossible.");   return n; } </PRE>  aurait pu tre crit dans l'exemple du carr magique.<BR> <BR>  <H3>A.2.10&nbsp;&nbsp;Entres-Sorties</H3>Nous ne considrons que quelques instructions simples permettant de lire ou crire dans une fentre texte ou avec un fichier. <CODE>System.in</CODE> et <CODE>System.out</CODE> sont deux champs statiques (donc uniques) de la classe systme, qui sont respectivement des <CODE>InputStream</CODE> et <CODE>PrintStream</CODE>. Dans cette dernire classe, il y a notamment les mthodes: <CODE>flush</CODE> qui vide les sorties non encore effectues, <CODE>print</CODE> et <CODE>println</CODE> qui impriment sur le terminal leur argument avec ventuellement un retour  la ligne. Pour l'impression, l'argument de ces fonctions est quelconque, (ventuellement vide pour la deuxime). Elles sont surcharges sur pratiquement tous les types, et transforment leur argument en chane de caractres. Ainsi:<BR> <BR> <PRE> System.out.println ("x= ")    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;donne     x = <I>newline</I> System.out.println (100)      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;     100 <I>newline</I>: System.out.print (3.14)       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;     3.14 System.out.print ("3.14")     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;     3.14 System.out.print (true)       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;     true System.out.print ("true")     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;     true </PRE>  Les mthodes des classes <CODE>InputStream</CODE> et <CODE>PrintStream</CODE> lisent ou impriment des octets (<CODE>byte</CODE>). Il vaut mieux faire des oprations avec des caractres Unicode (sur 16 bits, qui comprennent tous les caractres internationaux). Pour cela, au lieu de fonctionner avec les flux d'octets (<EM>Stream</EM> tout court), on utilise les classes des <EM>Reader</EM> ou des <EM>Writer</EM>, comme <CODE>InputStreamReader</CODE> et <CODE>OutputStreamWriter</CODE>, qui manipulent des flux de caractres. Dans ces classes, il existe de nombreuses mthodes ou fonctions. Ici, nous considrons les entres-sorties avec un tampon (<EM>buffer</EM> en anglais), qui sont plus efficaces, car elles regroupent les oprations d'entres-sorties. C'est pourquoi, on crit souvent la ligne cryptique:<BR> <BR> <PRE> struct Noeud {     BufferedReader in =          new BufferedReader(new InputStreamReader(System.in)); </PRE>  qui construit,  partir du flux de caractres <CODE>System.in</CODE> (dsignant la fentre d'entre de texte par dfaut), un flux de caractres, puis un flux de caractres avec tampon (plus efficace). Dans cette dernire classe, on lit les caractres par <CODE>read()</CODE> ou <CODE>readLine()</CODE>. Par convention, <CODE>read()</CODE> retourne -1 quand la fin de l'entre est dtecte (comme en C). C'est pourquoi le type de son rsultat est un entier (et non un caractre), puisque -1 ne peut pas tre du type caractre. Pour lire l'entre terminal et l'imprimer immdiatement, on fait donc: <A NAME="@default284"></A><A NAME="@default285"></A><BR> <BR> <PRE> import java.io.*;  static void copie () throws Exception {    BufferedReader in =        new BufferedReader(new InputStreamReader(System.in));   int c;    while ((c = in.read()) != -1)       System.out.println(c);   System.out.flush();   } </PRE>  Remarquons l'idiome pour lire un caractre. Il s'agit d'un effet de bord dans le prdicat du <CODE>while</CODE>. On fait l'affectation <CODE>c = in.read()</CODE> qui retourne comme rsultat la valeur de la partie droite (le caractre lu) et on teste si cette valeur vaut -1.<BR> <BR> <A NAME="@default286"></A><A NAME="@default287"></A><A NAME="@default288"></A><A NAME="@default289"></A><A NAME="@default290"></A><A NAME="@default291"></A><A NAME="@default292"></A><A NAME="@default293"></A>On peut aussi manipuler des fichiers, grce aux classes fichiers <CODE>File</CODE>. Ainsi le programme prcdent se rcrit pour copier un fichier source de nom <CODE>s</CODE> dans un autre destination de nom <CODE>d</CODE>.<BR> <BR> <PRE> import java.io.*;  static void copieDeFichiers (String s, String d) throws Exception {    File src = new File (s);   if ( !src.exists() || !src.canRead())       erreur ("Lecture impossible de " + s);   BufferedReader in = new BufferedReader(new FileReader(src));    File dest = new File (d);   if ( !dest.canWrite())       erreur ("Ecriture impossible de " + d);   BufferedWriter out = new BufferedWriter(new FileWriter(dest));    maCopie (in, out);   in.close();   out.close(); }  static void maCopie (BufferedReader in, BufferedWriter out)    throws IOException {    int c;   while ((c = in.read()) != -1)        out.write(c);   out.flush(); } </PRE>  La procdure de copie ressemble au programme prcdent, au changement prs de <CODE>print</CODE> en <CODE>write</CODE>, car nous n'avons pas voulu utiliser la classe <EM>Printer</EM>, ce qui tait faisable. Remarquons que les entres sorties se sont simplement faites avec les fichiers en suivant un shma quasi identique  celui utilis pour le terminal. La seule diffrence vient de l'association entre le nom de fichier et les flux de caractres tamponns. D'abord le nom de fichier est transform en objet <CODE>File</CODE> sur lequel plusieurs oprations sont possibles, comme vrifier l'existence ou les droits d'accs en lecture ou en criture. Puis on construit un objet de flux de caractres dans les classes <CODE>FileReader</CODE> et <CODE>FileWriter</CODE>, et enfin des objets de flux de caractres avec tampon. La procdure de copie est elle identique  celle vue prcdemment.<BR> <BR> On peut donc dire que l'entre standard <CODE>System.in</CODE> (de la fentre de texte), la sortie standard <CODE>System.out</CODE> (dans la fentre de texte), et la sortie standard des erreurs <CODE>System.err</CODE> (qui n'a vraiment de sens que dans le systme Unix) sont comme des fichiers particuliers. Les oprations de lecture ou d'criture tant les mmes. Seule la construction du flux de caractres tamponn varie.<BR> <BR> Enfin, on peut utiliser <CODE>mark</CODE>, <CODE>skip</CODE> et <CODE>reset</CODE> pour se positionner  une position prcise dans un fichier.<BR> <BR>  <H3>A.2.11&nbsp;&nbsp;Fonctions graphiques</H3><A NAME="@default294"></A><A NAME="@default295"></A><A NAME="@default296"></A><A NAME="@default297"></A><A NAME="E:quickdraw"></A> Les fonctions sont inspires de la libraire QuickDraw du Macintosh, mais fonctionnent aussi sur les stations Unix. Sur Macintosh, une fentre <EM>Drawing</EM> permet de grer un cran typiquement de 1024  768 points. L'origine du systme de coordonnes est en haut et  gauche. L'axe des <I>x</I> va classiquement de la gauche vers la droite, l'axe des <I>y</I> va plus curieusement du haut vers le bas (c'est une vieille tradition de l'informatique, dure  remettre en cause). En QuickDraw, <I>x</I> et <I>y</I> sont souvent appels <CODE>h</CODE> (horizontal) et <CODE>v</CODE> (vertical). Il y a une notion de point courant et de crayon avec une taille et une couleur courantes. On peut dplacer le crayon, en le levant ou en dessinant des vecteurs par les fonctions suivantes<BR> <BR> <DL> <DT><CODE>moveTo (x, y) </CODE><DD> Dplace le crayon aux coordonnes absolues <CODE>x</CODE>, <CODE>y</CODE>.<BR> <BR>  <DT><CODE>move (dx, dy) </CODE><DD> Dplace le crayon en relatif de <CODE>dx</CODE>, <CODE>dy</CODE>.<BR> <BR>  <DT><CODE>lineTo (x, y) </CODE><DD> Trace une ligne depuis le point courant jusqu'au point de coordonnes <CODE>x</CODE>, <CODE>y</CODE>.<BR> <BR>  <DT><CODE>line (dx, dy) </CODE><DD> Trace le vecteur (<CODE>dx</CODE>, <CODE>dy</CODE>) depuis le point courant.<BR> <BR>  <DT><CODE>penPat(pattern) </CODE><DD> Change la couleur du crayon: <CODE>white</CODE>, <CODE>black</CODE>, <CODE>gray</CODE>, <CODE>dkGray</CODE> (<EM>dark gray</EM>), <CODE>ltGray</CODE> (<EM>light gray</EM>).<BR> <BR>  <DT><CODE>penSize(dx, dy) </CODE><DD> Change la taille du crayon. La taille par dfaut est (1, 1). Toutes les oprations de trac peuvent se faire avec une certaine paisseur du crayon.<BR> <BR>  <DT><CODE>penMode(mode) </CODE><DD> Change le mode d'criture: <CODE>patCopy</CODE> (mode par dfaut qui efface ce sur quoi on trace), <CODE>patOr</CODE> (mode Union, i.e. sans effacer ce sur quoi on trace), <CODE>patXor</CODE> (mode Xor, i.e. en inversant ce sur quoi on trace).</DL>Certaines oprations sont possibles sur les rectangles. Un rectangle <CODE>r</CODE> a un type prdfini <CODE>Rect</CODE>. Ce type est une classe qui a le format suivant<BR> <BR> <PRE> public class Rect {    short left, top, right, bottom; } </PRE>  Fort heureusement, il n'y a pas besoin de connatre le format internes des rectangles, et on peut faire simplement les oprations graphiques suivantes sur les rectangles<BR> <BR> <A NAME="A:fns-quickdraw"></A> <DL> <DT><CODE>setRect(r, g, h, d, b) </CODE><DD> fixe les coordonnes (gauche, haut, droite, bas) du rectangle <CODE>r</CODE>. C'est quivalent  faire les oprations <CODE>r.left := g;</CODE>, <CODE>r.top := h;</CODE>,  <CODE>r.right := d;</CODE>, <CODE>r.bottom := b</CODE>.<BR> <BR>  <DT><CODE>unionRect(r1, r2, r) </CODE><DD> dfinit le rectangle <CODE>r</CODE> comme l'enveloppe englobante des rectangles <CODE>r1</CODE> et <CODE>r2</CODE>.<BR> <BR>  <DT><CODE>frameRect(r) </CODE><DD> dessine le cadre du rectangle <CODE>r</CODE> avec la largeur, la couleur et le mode du crayon courant.<BR> <BR>  <DT><CODE>paintRect(r) </CODE><DD> remplit l'intrieur du rectangle <CODE>r</CODE> avec la couleur courante.<BR> <BR>  <DT><CODE>invertRect(r) </CODE><DD> inverse la couleur du rectangle <CODE>r</CODE>.<BR> <BR>  <DT><CODE>eraseRect(r) </CODE><DD> efface le rectangle <CODE>r</CODE>.<BR> <BR>  <DT><CODE>fillRect(r,pat) </CODE><DD> remplit l'intrieur du rectangle <CODE>r</CODE> avec la couleur <CODE>pat</CODE>.<BR> <BR> <A NAME="@default298"></A> <DT><CODE>drawChar(c), drawString(s)</CODE><DD> affiche le caractre <CODE>c</CODE> ou la chane <CODE>s</CODE> au point courant dans la fentre graphique. Ces fonctions diffrent de <CODE>write</CODE> ou <CODE>writeln</CODE> qui crivent dans la fentre texte.<BR> <BR>  <DT><CODE>frameOval(r) </CODE><DD> dessine le cadre de l'ellipse inscrite dans le rectangle <CODE>r</CODE> avec la largeur, la couleur et le mode du crayon courant.<BR> <BR>  <DT><CODE>paintOval(r) </CODE><DD> remplit l'ellipse inscrite dans le rectangle <CODE>r</CODE> avec la couleur courante.<BR> <BR>  <DT><CODE>invertOval(r) </CODE><DD> inverse l'ellipse inscrite dans <CODE>r</CODE>.<BR> <BR>  <DT><CODE>eraseOval(r) </CODE><DD> efface l'ellipse inscrite dans <CODE>r</CODE>.<BR> <BR>  <DT><CODE>fillOval(r,pat) </CODE><DD> remplit l'intrieur l'ellipse inscrite dans <CODE>r</CODE> avec la couleur <CODE>pat</CODE>.<BR> <BR>  <DT><CODE>frameArc(r,start,arc) </CODE><DD> dessine l'arc de l'ellipse inscrite dans le rectangle <CODE>r</CODE> dmarrant  l'angle <CODE>start</CODE> et sur la longueur dfinie par l'angle <CODE>arc</CODE>.<BR> <BR>  <DT><CODE>frameArc(r,start,arc) </CODE><DD> peint le camembert correspondant  l'arc prcdent .... Il y a aussi des fonctions pour les rectangles avec des coins arrondis.<BR> <BR>  <DT><CODE>button </CODE><DD> est une fonction qui renvoie la valeur vraie si le bouton de la souris est enfonc, faux sinon.<BR> <BR>  <DT><CODE>getMouse(p) </CODE><DD> renvoie dans <CODE>p</CODE> le point de coordonnes (<CODE>p.h</CODE>, <CODE>p.v</CODE>) courantes du curseur.<BR> <BR>  <DT><CODE>getPixel(p) </CODE><DD> donne la couleur du point <CODE>p</CODE>. Rpond un boolen: <CODE>false</CODE> si blanc, <CODE>true.</CODE> si noir.<BR> <BR>  <DT><CODE>hideCursor(), showCursor() </CODE><DD> cache ou remontre le curseur.</DL><PRE> class Point {   short h, v;    Point(int h, int v) {     h = (short)h;     v = (short)v;   } } class MacLib {    static void setPt(Point p, int h, int v) {..}   static void addPt(Point src, Point dst) {...}   static void subPt(Point src, Point dst) {...}   static boolean equalPt(Point p1, Point p2) {...}   ... } </PRE>  Et les fonctions correspondantes (voir page <A HREF="main013.html#A:fns-quickdraw">X</A>)<BR> <BR> <PRE> static void setRect(Rect r, int left, int top, int right, int bottom) static void unionRect(Rect src1, Rect src2, Rect dst)  static void frameRect(Rect r) static void paintRect(Rect r) static void eraseRect(Rect r) static void invertRect(Rect r)  static void frameOval(Rect r) static void paintOval(Rect r) static void eraseOval(Rect r) static void invertOval(Rect r)  static void frameArc(Rect r, int startAngle, int arcAngle) static void paintArc(Rect r, int startAngle, int arcAngle) static void eraseArc(Rect r, int startAngle, int arcAngle) static void invertArc(Rect r, int startAngle, int arcAngle) static boolean button() static void getMouse(Point p) </PRE>  Toutes ces dfinitions sont aussi sur <CODE>poly</CODE> dans le fichier <PRE> /usr/local/lib/MacLib-java/MacLib.java </PRE>  On veillera  avoir cette classe dans l'ensemble des classes chargeables (variable d'environnement <CODE>CLASSPATH</CODE>). Le programme suivant est un programme qui fait rebondir une balle dans un rectangle, premire tape vers un jeu de <EM>pong</EM>.<BR> <BR> <PRE> class Pong extends MacLib {    static final int  C  =  5, // Le rayon de la balle        X0 =  5, X1 =  250,       Y0 =  5, Y1 =  180;    static void getXY (Point p) {     int N = 2;     Rect  r = new Rect();     int   x, y;      while (!button())        // On attend le bouton enfonc        ;     while (button())         // On attend le bouton relch        ;     getMouse(p);             // On note les coordonnes du pointeur      x = p.h;     y = p.v;     setRect(r, x - N, y - N, x + N, y + N);     paintOval(r);            // On affiche le point pour signifier la  lecture    }     public static void main (String args[]) {     int   x, y, dx, dy;     Rect  r = new Rect();     Rect  s = new Rect();     Point p = new Point();     int  i;      initQuickDraw();         // Initialisation du graphique      setRect(s, 50, 50, X1 + 100, Y1 + 100);     setDrawingRect(s);     showDrawing();     setRect(s, X0, Y0, X1, Y1);     frameRect(s);            // Le rectangle de jeu      getXY(p);                // On note les coordonnes du pointeur      x = p.h; y = p.v;     dx = 1;                  // La vitesse initiale      dy = 1;                  // de la balle      for (;;) {       setRect(r, x - C, y - C, x + C, y + C);       paintOval(r);          // On dessine la balle en <I>x</I>,<I>y</I>        x = x + dx;       if (x - C &lt;= X0 + 1 || x + C &gt;= X1 - 1)          dx = -dx;       y = y + dy;       if (y - C &lt;= Y0 + 1 || y + C &gt;= Y1 - 1)          dy = -dy;       for (i = 0; i &lt; 2500; ++i)         ;                    // On temporise        invertOval(r);         // On efface la balle      }   } } </PRE> <A NAME="toc54"></A> <H2>A.3&nbsp;&nbsp;Syntaxe BNF de Java</H2><A NAME="@default299"></A><A NAME="@default300"></A><A NAME="@default301"></A><A NAME="@default302"></A>Ce qui suit est une syntaxe sous forme BNF (<EM>Backus Naur Form</EM>). Chaque petit paragraphe est la dfinition souvent rcursive d'un fragment de syntaxe dnomme par un nom (malheureusement en anglais). Chaque ligne correspond  diffrentes dfinitions possibles. L'indice <EM>optional</EM> sera mis pour signaler l'aspect facultatif de l'objet indice. Certains objets (<EM>token</EM>) seront suppose predfinis: <EM>IntegerLiteral</EM> pour une constante entire, <EM>Identifier</EM> pour tout identificateur, ...La syntaxe du langage ne garantit pas la concordance des types, certaines phrases pouvant tre syntaxiquement correctes, mais fausses pour les types.<BR> <BR> <PRE> Goal:  CompilationUnit </PRE><FONT SIZE=2> </FONT>   <H3>A.3.1&nbsp;&nbsp;Contantes littrales</H3><PRE> Literal:  IntegerLiteral  FloatingPointLiteral  BooleanLiteral  CharacterLiteral  StringLiteral  NullLiteral </PRE><FONT SIZE=2> </FONT>   <H3>A.3.2&nbsp;&nbsp;Types, valeurs, et variables</H3><PRE> Type:  PrimitiveType  ReferenceType  PrimitiveType:  NumericType  boolean  NumericType:  IntegralType  FloatingPointType  IntegralType: one of  byte short int long char  FloatingPointType: one of  float double  ReferenceType:  ClassOrInterfaceType  ArrayType  ClassOrInterfaceType:  Name  ClassType:  ClassOrInterfaceType  InterfaceType:  ClassOrInterfaceType  ArrayType:  PrimitiveType [ ]  Name [ ]  ArrayType [ ] </PRE><FONT SIZE=2> </FONT>   <H3>A.3.3&nbsp;&nbsp;Noms</H3><PRE> Name:  SimpleName  QualifiedName  SimpleName:  Identifier  QualifiedName:  Name . Identifier </PRE><FONT SIZE=2> </FONT>   <H3>A.3.4&nbsp;&nbsp;Packages</H3><PRE> CompilationUnit:  PackageDeclaration$_<FONT SIZE=2><I>opt</I></FONT>$ ImportDeclarations$_<FONT SIZE=2><I>opt</I></FONT>$ TypeDeclarations$_<FONT SIZE=2><I>opt</I></FONT>$  ImportDeclarations:  ImportDeclaration  ImportDeclarations ImportDeclaration  TypeDeclarations:  TypeDeclaration  TypeDeclarations TypeDeclaration  PackageDeclaration:  package Name ;  ImportDeclaration:  SingleTypeImportDeclaration  TypeImportOnDemandDeclaration  SingleTypeImportDeclaration:  import Name ;  TypeImportOnDemandDeclaration:  import Name . * ;  TypeDeclaration:  ClassDeclaration  InterfaceDeclaration  ;  Modifiers:  Modifier  Modifiers Modifier  Modifier: one of  public protected private  static  abstract final native synchronized transient volatile </PRE><FONT SIZE=2> </FONT>   <H3>A.3.5&nbsp;&nbsp;Classes</H3> <H4>Dclaration de classe</H4><PRE> ClassDeclaration:  Modifiers$_<FONT SIZE=2><I>opt</I></FONT>$ class Identifier Super$_<FONT SIZE=2><I>opt</I></FONT>$ Interfaces$_<FONT SIZE=2><I>opt</I></FONT>$ ClassBody  Super:  extends ClassType  Interfaces:  implements InterfaceTypeList  InterfaceTypeList:  InterfaceType  InterfaceTypeList , InterfaceType  ClassBody:  {ClassBodyDeclarations$_<FONT SIZE=2><I>opt</I></FONT>$ }<BR> <BR> ClassBodyDeclarations:  ClassBodyDeclaration  ClassBodyDeclarations ClassBodyDeclaration  ClassBodyDeclaration:  ClassMemberDeclaration  StaticInitializer  ConstructorDeclaration  ClassMemberDeclaration:  FieldDeclaration  MethodDeclaration </PRE><FONT SIZE=2> </FONT>   <H4>Dclarations de champs</H4><PRE> FieldDeclaration:  Modifiers$_<FONT SIZE=2><I>opt</I></FONT>$ Type VariableDeclarators ;  VariableDeclarators:  VariableDeclarator  VariableDeclarators , VariableDeclarator  VariableDeclarator:  VariableDeclaratorId  VariableDeclaratorId = VariableInitializer  VariableDeclaratorId:  Identifier  VariableDeclaratorId [ ]  VariableInitializer:  Expression  ArrayInitializer </PRE><FONT SIZE=2> </FONT>   <H4>Dclarations de mthodes</H4><PRE> MethodDeclaration:  MethodHeader MethodBody  MethodHeader:  Modifiers$_<FONT SIZE=2><I>opt</I></FONT>$ Type MethodDeclarator Throws$_<FONT SIZE=2><I>opt</I></FONT>$  Modifiers$_<FONT SIZE=2><I>opt</I></FONT>$ void MethodDeclarator Throws$_<FONT SIZE=2><I>opt</I></FONT>$  MethodDeclarator:  Identifier ( FormalParameterList$_<FONT SIZE=2><I>opt</I></FONT>$ )  MethodDeclarator [ ]  FormalParameterList:  FormalParameter  FormalParameterList , FormalParameter  FormalParameter:  Type VariableDeclaratorId  Throws:  throws ClassTypeList  ClassTypeList:  ClassType  ClassTypeList , ClassType  MethodBody:  Block   ; </PRE><FONT SIZE=2> </FONT>   <H4>Initialieurs statiques</H4><PRE> StaticInitializer:  static Block </PRE><FONT SIZE=2> </FONT>   <H4>Dclarations de constructeurs</H4><PRE> ConstructorDeclaration:  Modifiers$_<FONT SIZE=2><I>opt</I></FONT>$ ConstructorDeclarator Throws$_<FONT SIZE=2><I>opt</I></FONT>$ ConstructorBody  ConstructorDeclarator:  SimpleName ( FormalParameterList$_<FONT SIZE=2><I>opt</I></FONT>$ )  ConstructorBody:  {ExplicitConstructorInvocation$_<FONT SIZE=2><I>opt</I></FONT>$ BlockStatements$_<FONT SIZE=2><I>opt</I></FONT>$ }<BR> <BR> ExplicitConstructorInvocation:  this ( ArgumentList$_<FONT SIZE=2><I>opt</I></FONT>$ ) ;  super ( ArgumentList$_<FONT SIZE=2><I>opt</I></FONT>$ ) ; </PRE><FONT SIZE=2> </FONT>   <H3>A.3.6&nbsp;&nbsp;Interfaces</H3><PRE> InterfaceDeclaration:  Modifiers$_<FONT SIZE=2><I>opt</I></FONT>$ interface Identifier ExtendsInterfaces$_<FONT SIZE=2><I>opt</I></FONT>$ InterfaceBody  ExtendsInterfaces:  extends InterfaceType  ExtendsInterfaces , InterfaceType  InterfaceBody:  {InterfaceMemberDeclarations$_<FONT SIZE=2><I>opt</I></FONT>$ }<BR> <BR> InterfaceMemberDeclarations:  InterfaceMemberDeclaration  InterfaceMemberDeclarations InterfaceMemberDeclaration  InterfaceMemberDeclaration:  ConstantDeclaration  AbstractMethodDeclaration  ConstantDeclaration:  FieldDeclaration  AbstractMethodDeclaration:  MethodHeader ; </PRE><FONT SIZE=2> </FONT>   <H3>A.3.7&nbsp;&nbsp;Tableaux</H3><PRE> ArrayInitializer:  {VariableInitializers$_<FONT SIZE=2><I>opt</I></FONT>$ ,$_<FONT SIZE=2><I>opt</I></FONT>$ }<BR> <BR> VariableInitializers:  VariableInitializer  VariableInitializers , VariableInitializer </PRE><FONT SIZE=2> </FONT>   <H3>A.3.8&nbsp;&nbsp;Blocs et instructions</H3><PRE> Block:  {BlockStatements$_<FONT SIZE=2><I>opt</I></FONT>$ }<BR> <BR> BlockStatements:  BlockStatement  BlockStatements BlockStatement  BlockStatement:  LocalVariableDeclarationStatement  Statement  LocalVariableDeclarationStatement:  LocalVariableDeclaration ;  LocalVariableDeclaration:  Type VariableDeclarators  Statement:  StatementWithoutTrailingSubstatement  LabeledStatement  BlockStatementsBlockStatementsIfThenStatement  IfThenElseStatement  WhileStatement  ForStatement  StatementNoShortIf:  StatementWithoutTrailingSubstatement  LabeledStatementNoShortIf  IfThenElseStatementNoShortIf  WhileStatementNoShortIf  ForStatementNoShortIf  StatementWithoutTrailingSubstatement:  Block  EmptyStatement  ExpressionStatement  SwitchStatement  DoStatement  BreakStatement  ContinueStatement  ReturnStatement  SynchronizedStatement  ThrowStatement  TryStatement  EmptyStatement:  ;  LabeledStatement:  Identifier : Statement  LabeledStatementNoShortIf:  Identifier : StatementNoShortIf  ExpressionStatement:  StatementExpression ;  StatementExpression:  Assignment  PreIncrementExpression  PreDecrementExpression  PostIncrementExpression  PostDecrementExpression  MethodInvocation  ClassInstanceCreationExpression  IfThenStatement:  if ( Expression ) Statement  IfThenElseStatement:  if ( Expression ) StatementNoShortIf else Statement  IfThenElseStatementNoShortIf:  if ( Expression ) StatementNoShortIf else StatementNoShortIf  SwitchStatement:  switch ( Expression ) SwitchBlock  SwitchBlock:  {SwitchBlockStatementGroups$_<FONT SIZE=2><I>opt</I></FONT>$ SwitchLabels$_<FONT SIZE=2><I>opt</I></FONT>$ }<BR> <BR> SwitchBlockStatementGroups:  SwitchBlockStatementGroup  SwitchBlockStatementGroups SwitchBlockStatementGroup  SwitchBlockStatementGroup:  SwitchLabels BlockStatements  SwitchLabels:  SwitchLabel  SwitchLabels SwitchLabel  SwitchLabel:  case ConstantExpression :  default :  WhileStatement:  while ( Expression ) Statement  WhileStatementNoShortIf:  while ( Expression ) StatementNoShortIf  DoStatement:  do Statement while ( Expression ) ;  ForStatement:  for ( ForInit$_<FONT SIZE=2><I>opt</I></FONT>$ ; Expression$_<FONT SIZE=2><I>opt</I></FONT>$ ; ForUpdate$_<FONT SIZE=2><I>opt</I></FONT>$ )  Statement  ForStatementNoShortIf:  for ( ForInit$_<FONT SIZE=2><I>opt</I></FONT>$ ; Expression$_<FONT SIZE=2><I>opt</I></FONT>$ ; ForUpdate$_<FONT SIZE=2><I>opt</I></FONT>$ )  StatementNoShortIf  ForInit:  StatementExpressionList  LocalVariableDeclaration  ForUpdate:  StatementExpressionList  StatementExpressionList:  StatementExpression  StatementExpressionList , StatementExpression  BreakStatement:  break Identifier$_<FONT SIZE=2><I>opt</I></FONT>$ ;  ContinueStatement:  continue Identifier$_<FONT SIZE=2><I>opt</I></FONT>$ ;  ReturnStatement:  return Expression$_<FONT SIZE=2><I>opt</I></FONT>$ ;  ThrowStatement:  throw Expression ;  SynchronizedStatement:  synchronized ( Expression ) Block  TryStatement:  try Block Catches  try Block Catches$_<FONT SIZE=2><I>opt</I></FONT>$ Finally  Catches:  CatchClause  Catches CatchClause  CatchClause:  catch ( FormalParameter ) Block  Finally:  finally Block </PRE><FONT SIZE=2> </FONT>   <H3>A.3.9&nbsp;&nbsp;Expressions</H3><PRE> Primary:  PrimaryNoNewArray  ArrayCreationExpression  PrimaryNoNewArray:  Literal  this  ( Expression )  ClassInstanceCreationExpression  FieldAccess  MethodInvocation  ArrayAccess  ClassInstanceCreationExpression:  new ClassType ( ArgumentList$_<FONT SIZE=2><I>opt</I></FONT>$ )  ArgumentList:  Expression  ArgumentList , Expression  ArrayCreationExpression:  new PrimitiveType DimExprs Dims$_<FONT SIZE=2><I>opt</I></FONT>$  new ClassOrInterfaceType DimExprs Dims$_<FONT SIZE=2><I>opt</I></FONT>$  DimExprs:  DimExpr  DimExprs DimExpr  DimExpr:  [ Expression ]  Dims:  [ ]  Dims [ ]  FieldAccess:  Primary . Identifier  super . Identifier  MethodInvocation:  Name ( ArgumentList$_<FONT SIZE=2><I>opt</I></FONT>$ )  Primary . Identifier ( ArgumentList$_<FONT SIZE=2><I>opt</I></FONT>$ )  super . Identifier ( ArgumentList$_<FONT SIZE=2><I>opt</I></FONT>$ )  ArrayAccess:  Name [ Expression ]  PrimaryNoNewArray [ Expression ]  PostfixExpression:  Primary  Name  PostIncrementExpression  PostDecrementExpression  PostIncrementExpression:  PostfixExpression ++  PostDecrementExpression:  PostfixExpression --  UnaryExpression:  PreIncrementExpression  PreDecrementExpression  + UnaryExpression  - UnaryExpression  UnaryExpressionNotPlusMinus  PreIncrementExpression:  ++ UnaryExpression  PreDecrementExpression:  -- UnaryExpression  UnaryExpressionNotPlusMinus:  PostfixExpression  &nbsp; UnaryExpression  ! UnaryExpression  CastExpression  CastExpression:  ( PrimitiveType Dims$_<FONT SIZE=2><I>opt</I></FONT>$ ) UnaryExpression  ( Expression ) UnaryExpressionNotPlusMinus  ( Name Dims ) UnaryExpressionNotPlusMinus  MultiplicativeExpression:  UnaryExpression  MultiplicativeExpression * UnaryExpression  MultiplicativeExpression / UnaryExpression  MultiplicativeExpression  AdditiveExpression:  MultiplicativeExpression  AdditiveExpression + MultiplicativeExpression  AdditiveExpression - MultiplicativeExpression  ShiftExpression:  AdditiveExpression  ShiftExpression &lt;&lt; AdditiveExpression  ShiftExpression &gt;&gt; AdditiveExpression  ShiftExpression &gt;&gt;&gt; AdditiveExpression  RelationalExpression:  ShiftExpression  RelationalExpression &lt; ShiftExpression  RelationalExpression &gt; ShiftExpression  RelationalExpression &lt;= ShiftExpression  RelationalExpression &gt;= ShiftExpression  RelationalExpression instanceof ReferenceType  EqualityExpression:  RelationalExpression  EqualityExpression == RelationalExpression  EqualityExpression != RelationalExpression  AndExpression:  EqualityExpression  AndExpressionEqualityExpression  ExclusiveOrExpression:  AndExpression  ExclusiveOrExpression ^ AndExpression  InclusiveOrExpression:  ExclusiveOrExpression  InclusiveOrExpression | ExclusiveOrExpression  ConditionalAndExpression:  InclusiveOrExpression  ConditionalAndExpressionInclusiveOrExpression  ConditionalOrExpression:  ConditionalAndExpression  ConditionalOrExpression || ConditionalAndExpression  ConditionalExpression:  ConditionalOrExpression  ConditionalOrExpression ? Expression : ConditionalExpression  AssignmentExpression:  ConditionalExpression  Assignment  Assignment:  LeftHandSide AssignmentOperator AssignmentExpression  LeftHandSide:  Name  FieldAccess  ArrayAccess  AssignmentOperator: one of  = *= /=  Expression:  AssignmentExpression  ConstantExpression:  Expression </PRE><FONT SIZE=2> </FONT>   <H2>Bibliographie Java</H2><UL> <LI>[<I>j</I>1] <EM>Exploring Java</EM>, 2nd edition, Pat Niemeyer et Joshua Peck 628 pages, O'Reilly, ISBN: 1-56592-271-9. 1997.<BR> <BR>  <LI>[<I>j</I>2] <EM>The Java Language Specification</EM>, James Gosling, Bill Joy et Guy Steele, Addison Wesley, ISBN: 0-201-63456-2. 1996.<BR> <BR>  <LI>[<I>j</I>3] <EM>Java in a Nutshell</EM>, David Flanagan, O'Reilly, ISBN: 1-56592-262-X, 1997.<BR> <BR>  <LI>[<I>j</I>4] <EM>Java examples in a Nutshell</EM>, David Flanagan, O'Reilly, ISBN: 1-56592-371-5. 1997.</UL>   <HR> <A HREF="main012.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A> <A HREF="main014.html"><IMG SRC ="next_motif.gif" ALT="Next"></A> <A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A> </BODY> </HTML> 
