Introduction aux bases de Java 2
Apparu fin 1995 début 1996 et développé par Sun Microsystems Java s'est très rapidement taillé une place importante en particulier dans le domaine de l'internet et des applications client-serveur.
Destiné au départ à la programmation de centraux téléphoniques sous l'appellation de langage "oak", la société Sun a eu l'idée de le recentrer sur les applications de l'internet et des réseaux. C'est un langage en évolution permanente Java 2 est la version stabilisée de java fondée sur la version initiale 1.2.2 du JDK (Java Development Kit de Sun : )
Les objectifs de java sont d'être multi-plateformes et d'assurer la sécurité aussi bien pendant le développement que pendant l'utilisation d'un programme java. Il est en passe de détrôner le langage C++ dont il hérite partiellement la syntaxe mais non ses défauts. Comme C++ et Delphi, java est algorithmique et orienté objet à ce titre il peut effectuer comme ses compagnons, toutes les tâches d'un tel langage (bureautiques, graphiques, multimédias, bases de données, environnement de développement, etc ). Son point fort qui le démarque des autres est sa portabilité due (en théorie) à ses bibliothèques de classes indépendantes de la plate-forme, ce qui est le point essentiel de la programmation sur internet ou plusieurs machines dissemblables sont interconnectées.
La réalisation multi-plateformes dépend en fait du système d'exploitation et de sa capacité à posséder des outils de compilation et d'interprétation de la machine virtuelle Java. Actuellement ceci est totalement réalisé d'une manière correcte sur les plates-formes Windows et Solaris, un peu moins bien sur les autres semble-t-il.
Notre document se posant en manuel d'initiation nous ne comparerons pas C++ et java afin de voir les points forts de java, sachons que dans java ont été éliminés tous les éléments qui permettaient dans C++ d'engendrer des erreurs dans le code (pointeurs, allocationdésallocation, héritage multiple, ). Ce qui met java devant C++ au rang de la maintenance et de la sécurité.
En Java l'on développe deux genres de programmes :
HTML.
Les types primitifs
Java 2
1 - Les types élémentaires et le transtypage
Tout n'est pas objet dans Java, par souci de simplicité et d'efficacité, Java est un langage fortement typé. Comme en Delphi, en Java vous devez déclarer un objet ou une variable avec son type avant de l'utiliser. Java dispose de même de types prédéfinis ou types élémentaires ou primitifs.
Les types servent à déterminer la nature du contenu d'une variable, du résultat d'une opération, d'un retour de résultat de fonction.
Tableau synthétique des types élémentaires de Java
type élémentaire |
intervalle de variation |
nombre de bits |
boolean |
false , true |
1 bit |
byte |
[-128 , +127 ] |
8 bits |
char |
caractères unicode (valeurs de 0 à 65536) |
16 bits |
double |
Virgule flottante double précision ~5.10 308 |
64 bits |
float |
Virgule flottante simple précision ~9.10 18 |
32 bits |
int |
entier signé : [-231, +231 - 1] |
32 bits |
long |
entier signé long : [-263, +263- 1 ] |
64 bits |
short |
entier signé court : [-215, +215 -1] |
16 bits |
Signalons qu'en java toute variable qui sert de conteneur à une valeur d'un type élémentaire précis doit préalablement avoir été déclarée sous ce type.
Il est possible d'indiquer au compilateur le type d'une valeur numérique en utilisant un suffixe :
? |
l ou L pour désigner un entier du type long |
? |
f ou F pour désigner un réel du type float |
? |
d ou D pour désigner un réel du type double. |
Exemples :
45l ou 45Lreprésente la valeur 45 en entier signé sur 64 bits.
45f ou 45Freprésente la valeur 45 en virgule flottante simple précision sur 32 bits.
45d ou 45Dreprésente la valeur 45 en virgule flottante double précision sur
64 bits.
5.27e-2f ou 5.27e-2Freprésente la valeur 0.0527 en virgule flottante simple précision sur 32 bits.
Transtypage : opérateur ()
Les conversions de type en Java sont identiques pour les types numériques aux conversions utilisées dans un langage fortement typé comme Delphi par exemple (pas de conversion implicite). Si vous voulez malgré tout, convertir une valeur immédiate ou une valeur contenue dans une variable il faut explicitement transtyper cette valeur à l'aide de l'opérateur de transtypage noté: ( ).
x = (int) y ; signifie que vous demander de transtyper la valeur contenue dans la variable y en un entier signé 32 bits avant de la mettre dans la variable x.
2 - Variables, valeurs, constantes
Identificateurs de variables
Déclarations et affectation de variables
Les constantes en Java
Base de représentation des entiers
Comme en Delphi, une variable Java peut contenir soit une valeur d'un type élémentaire, soit une référence à un objet. Les variables jouent le même rôle que dans les langages de programmation classiques impératifs, leur visibilité est étudiée ailleurs.
Les identificateurs de variables en Java se décrivent comme ceux de tous les langages de programmation :
Identificateur Java :
Attention Java est sensible à la casse et fait donc une différence entre majuscules et minuscules, c'est à dire que la variable BonJour n'est pas la même que la variable bonjour ou encore la variable Bonjour. En plus des lettres, les caractères suivants sont autorisés pour construire un identificateur Java : "$" , "_" , "µ" et les lettres accentuées.
Exemples de déclaration de variables :
int Bonjour ; int µEnumération_fin$;
float Valeur ; char UnCar ; boolean Test ;
etc
Exemples d'affectation de valeurs à ces variables :
Affectation Déclaration avec initialisation
Bonjour = 2587 ;
Valeur = -123.5687
UnCar = 'K' ;
int Bonjour = 2587 ; float Valeur = -123.5687 char UnCar = 'K' ;
Test = false ; boolean Test = false ;
Exemple avec transtypage :
int Valeur ; char car = '8' ;
Valeur = (int)car - (int)'0';
fonctionnement de l'exemple :
Lorsque la variable car est l'un des caractères '0', '1', ,'9', la variable Valeur est égale à la valeur numérique associée (il s'agit d'une conversion car = '0' ---> Valeur = 0, car = '1' ---> Valeur = 1, , car = '9' ---> Valeur = 9).
Les constantes en Java ressemblent à celles du pascal
Ce sont des variables dont le contenu ne peut pas être modifié, elles sont précédées du mot clef final :
final int x=10 ; x est déclarée comme constante entière initialisée à 10.
x = 32 ;
Une constante peut être déclarée et initialisée plus loin une seule fois : final int x ; ….. x = 10;
Base de représentation des entiers
Java peut représenter les entiers dans 3 bases de numération différentes : décimale (base 10), octale (base 8), hexadécimale (base 16). La détermination de la base de représentation d'une valeur est d'ordre syntaxique grâce à un préfixe :
? |
pas de préfixe ----> base = 10décimal. |
|
? |
préfixe 0 |
----> base = 8 octal |
? |
préfixe 0x ----> base = 16 hexadécimal |
3 - Priorité d'opérateurs
Les 39 opérateurs de Java sont détaillés par famille, plus loin . Ils sont utilisés comme dans tous les langages impératifs pour manipuler, séparer, comparer ou stocker des valeurs. Les opérateurs ont soit un seul opérande, soit deux opérandes, il n'existe en Java qu'un seul opérateur à trois opérandes (comme en C) l'opérateur conditionnel "? : ".
Dans le tableau ci-dessous les opérateurs de Java sont classés par ordre de priorité croissante (0 est le plus haut niveau, 14 le plus bas niveau). Ceci sert lorsqu'une expression contient plusieurs opérateurs, à indiquer l'ordre dans lequel s'effectueront les opérations.
Les opérateurs
Java 2
Opérateurs arithmétiques
Opérateurs de comparaison
Opérateurs booléens
Opérateurs bit level
1 - Opérateurs arithmétiques
opérateurs travaillant avec des opérandes à valeur immédiate ou variable
Opérateur |
priorité |
action |
exemples |
+ |
1 |
signe positif |
+a; +(a-b); +7 (unaire) |
- |
1 |
signe négatif |
-a; -(a-b); -7 (unaire) |
* |
2 |
multiplication |
5*4; 12.7*(-8.31); 5*2.6 |
/ |
2 |
division |
5 / 2; 5.0 / 2; 5.0 / 2.0 |
% |
2 |
reste |
5 % 2; 5.0 %2; 5.0 % 2.0 |
+ |
3 |
addition |
a+b; -8.53 + 10; 2+3 |
- |
3 |
soustraction |
a-b; -8.53 - 10; 2-3 |
Ces opérateurs sont binaires (à deux opérandes) exceptés les opérateurs de signe positif ou négatif. Ils travaillent tous avec des opérandes de types entiers ou réels. Le résultat de l'opération est converti automatiquement en valeur du type des opérandes.
L'opérateur " % " de reste n'est intéressant que pour des calculs sur les entiers longs, courts, signés ou non signés : il renvoie le reste de la division euclidienne de 2 entiers.
... ... ...
Rappelons tout d'abord quelques principes de base :
Dans tous les langages possédant la notion de sous-programme (ou fonction ou procédure), il se pose une question à savoir, les paramètres formels décrits lors de la déclaration d'un sousprogramme ne sont que des variables muettes servant à expliquer le fonctionnement du sousprogramme sur des futures variables lorsque le sous-programme s'exécutera effectivement.
La démarche en informatique est semblable à celle qui, en mathématiques, consiste à écrire la fonction f(x) = 3*x - 7, dans laquelle x alors une variable muette indiquant comment f est calculée : en informatique elle joue le rôle du paramètre formel. Lorsque l'on veut obtenir une valeur effective de la fonction mathématique f, par exemple pour x=2, on écrit f(2) et l'on calcule f(2)=3*2 - 7 = -1. En informatique on "passera" un paramètre effectif dont la valeur vaut 2 à la fonction. D'une manière générale, en informatique, il y a un sous-programme appelant et un sous-programme appelé par le sous-programme appelant.
Compatibilité des types des paramètres
Resituons la compatibilité des types entier et réel en Java. Un moyen mnémotechnique pour retenir cette compatibilité est indiqué dans les figures ci-dessous, par la taille en nombre décroissant de bits de chaque type que l'on peut mémoriser sous la forme "qui peut le plus peut le moins" ou bien un type à n bits accueillera un sous-type à p bits, si p est inférieur à n.
Les types réels compatibles :
Les types entiers compatibles :
Exemple d'appel de la même méthode-procédure avec paramètres de type compatibles en Java
class Application5 { static void main(String[ ] args) {// recherche séquentielle dans un tableauint [ ] table= {12,-5,7,8,-6,6,4,78,2}; byte elt = 4; short i ; for ( i = 0 ; iif (elt= =table[i]) break ; afficher(i,elt); } static void afficher (int rang , long val) { if (rang == 8) |
Appel de la méthode afficher afficher(i,elt); Les deux paramètres effectifs "i" et "elt" sont d'un type compatible avec celui du paramètre formel associé. - Le paramètre effectif "i" est associé au paramètre formel rang.(short = entier signé sur 16 bits et int = entier signé sur 32 bits) |
.println("valeur : "+val+" pas trouvée."); else .println("valeur : "+val+" trouvée au rang :"+ rang); } } |
- Le paramètre effectif "elt" est associé au paramètre formel val.(byte = entier signé sur 8 bits et long = entier signé sur 64 bits) |
Les deux modes de transmission des paramètres
Un paramètre effectif transmis au sous-programme appelé est en fait un moyen d’utiliser ou d’accéder à une information appartenant au bloc appelant (le bloc appelé peut être le même que le bloc appelant, il s’agit alors de récursivité).
En Java, il existe deux modes de transmission (ou de passage) des paramètres (semblables à Delphi).
Le passage par valeur uniquement réservé à tous les types élémentaires
(int, byte, short, long, boolean, double, float, char).
Le passage par référence uniquement réservé à tous les types objets.
Remarque :
Le choix de passage selon les types élimine les inconvénients dûs à l'encombrement mémoire et à la lenteur de recopie de la valeur du paramètre par exemple dans un passage par valeur, car nous verrons plus loin que les tableaux en Java sont des objets et qu'ils sont donc passés par référence.
Les retours de résultat de méthode-fonction
Les méthodes en Java peuvent renvoyer un résultat de n'importe quel type élémentaire ou objet. Bien qu'une méthode ne puisse renvoyer qu'un seul résultat, l'utilisation du passage par référence d'objets permet aussi d'utiliser les paramètres de type objet d'une méthode comme des variables d'entrée/sortie.
En Java le retour de résultat est passé grâce au mot clef return placé n'importe où dans le corps de la méthode.
Syntaxe :
Sémantique :
Exemple la fonction f(x)=3x-7
... ... ...
Les interfaces
Java2
Introduction
Vocabulaire et concepts :
? |
Une interface est un contrat, elle peut contenir des propriétés, des méthodes et des événements mais ne doit contenir aucun champ ou attribut. |
? |
Une interface ne peut pas contenir des méthodes déjà implémentées. |
? |
Une interface doit contenir des méthodes non implémentées. |
? |
Une interface est héritable. |
? |
On peut construire une hiérarchie d'interfaces. |
? |
Pour pouvoir construire un objet à partir d'une interface, il faut définir une classe non abstraite implémentant toutes les méthodes de l'interface. |
Une classe peut implémenter plusieurs interfaces. Dans ce cas nous avons une excellente alternative à l'héritage multiple.
Lorsque l'on crée une interface, on fournit un ensemble de définitions et de comportements qui ne devraient plus être modifiés. Cette attitude de constance dans les définitions, protège les applications écrites pour utiliser cette interface.
Les variables de types interface respectent les mêmes règles de transtypage que les variables de types classe.
Les objets de type classe clA peuvent être transtypés et reférencés par des variables d'interface IntfA dans la mesure où la classe clA implémente l’interface IntfA. (cf. polymorphisme d'objet)
Si vous voulez utiliser la notion d'interface pour fournir un polymorphisme à une famille de classes, elles doivent toutes implémenter cette interface, comme dans l'exemple ci-dessous. Exemple :
l'interface Véhicule définissant 3 méthodes (abstraites) Démarrer, RépartirPassagers de répartition des passagers à bord du véhicule (fonction de la forme, du nombre de places, du personnel chargé de s'occuper de faire fonctionner le véhicule ), et PériodicitéMaintenance renvoyant la périodicité de la maintenance obligatoire du véhicule (fonction du nombre de kms ou miles parcourus, du nombre d'heures d'activités, ) Soit l'interface Véhicule définissant ces 3 méthodes :
Soient les deux classes Véhicule terrestre et Véhicule marin, qui implémentent partiellement chacune l'interface Véhicule , ainsi que trois classes voiture, voilier et croiseur héritant de ces deux classes :
abstraite Démarrer de l'interface Véhicule n'est pas implémentée elle reste comme "modèle" aux futurs classes. C'est dans les classes voiture, voilier et croiseur que l'on implémente le comportement précis du genre de démarrage.
Exemple de hiérarchie à partir d'une interface :
Dans cet exemple :
Les méthodes RépartirPassagers, PériodicitéMaintenance et Demarrer sont implantées soit comme des méthodes à liaison dynamique afin de laisser la possibilité pour des classes enfants de surcharger ces méthodes.
Soit l'écriture en Java de cet l'exemple :
interface IVehicule{ void Demarrer( ); void RépartirPassager( ); void PériodicitéMaintenance( ); } abstract class Terrestre implements IVehicule { public void RépartirPassager( ){ .}; public void PériodicitéMaintenance( ){ .}; } class Voiture extends Terrestre { public void Demarrer( ){ .}; } abstract class Marin implements IVehicule { |
public void RépartirPassager( ){ .}; public void PériodicitéMaintenance( ){ .}; } class Voilier extends Marin { public void Demarrer( ){ .}; } class Croiseur extends Marin { public void Demarrer( ){ .}; } |
Java2 à la fenêtre avec Awt
IHM avec Java
Java, comme tout langage moderne, permet de créer des applications qui ressemblent à l'interface du système d'exploitation. Cette assurance d'ergonomie et d'interactivité avec l'utilisateur est le minimum qu'un utilisateur demande à une application. Les interfaces homme-machine (dénommées IHM) font intervenir de nos jours des éléments que l'on retrouve dans la majorité des systèmes d'exploitation : les fenêtres, les menus déroulants, les boutons, etc
Ce chapitre traite en résumé, mais en posant toutes les bases, de l'aptitude de Java à élaborer une IHM. Nous regroupons sous le vocable d'IHM Java, les applications disposant d'une interface graphique et les applets que nous verrons plus loin.
Le package AWT
C'est pour construire de telles IHM que le package AWT (Abstract Window Toolkit) est inclu dans toutes les versions de Java. Ce package est la base des extensions ultérieures comme Swing, mais est le seul qui fonctionne sur toutes les générations de navigateurs.
Les classes contenues dans AWT dérivent (héritent) toutes de la classe Component, nous allons étudier quelques classes minimales pour construire une IHM standard.
Ces classes sont essentielles pour la construction d'IHM Java elles dérivent de la classe .Container, elles permettent d'intégrer d'autres objets visuels et de les organiser à l'écran.
Hiérarchie de la classe Container : .Object |
| .Component |
| +--.Container |
Voici la liste extraite du JDK des sous-classes de la classe Container autres que Swing : Panel, ScrollPane, Window.
Les principales classes conteneurs :
Classe |
Fonction |
.Container | +--.Window |
Crée des rectangles simples sans cadre, sans menu, sans titre, mais ne permet pas de créer directement une fenêtre Windows classique. |
.Container | +--.Panel |
Crée une surface sans bordure, capable de contenir d'autres éléments : boutons, panel etc |
.Container | +--.ScrollPane |
Crée une barre de défilement horizontale et/ou une barre de défilement verticale. |
Les classes héritées des classes conteneurs :
Classe |
Fonction |
.Window | +--.Frame |
Crée des fenêtres avec bordure, pouvant intégrer des menus, avec un titre, etc comme toute fenêtre Windows classique. C'est le conteneur de base de toute application graphique. |
.Window | +--.Dialog |
Crée une fenêtre de dialogue avec l'utilisateur, avec une bordure, un titre et un bouton-icône de fermeture. |
Une première fenêtre construite à partir d'un objet de classe Frame; une fenêtre est donc un objet, on pourra donc créer autant de fenêtres que nécessaire, il suffira à chaque fois d'instancier un objet de la classe Frame.
Quelques méthodes de la classe Frame, utiles au départ :
Méthodes |
Fonction |
public void setSize(int width, int height) |
retaille la largeur (width) et la hauteur (height) de la fenêtre. |
public void setBounds(int x, int y, int width, int height) |
retaille la largeur (width) et la hauteur (height) de la fenêtre et la positionne en x,y sur l'écran. |
public Frame(String title) public Frame( ) |
Les deux constructeurs d'objets Frame, celui qui possède un paramètre String écrit la chaîne dans la barre de titre de la fenêtre. |
public void setVisible(boolean b ) |
Change l'état de la fenêtre en mode visible ou invisible selon la valeur de b. |
public void hide( ) |
Change l'état de la fenêtre en mode invisible. |
Différentes surcharges de la méthode add : publicComponent add(Component comp) etc |
Permettent d'ajouter un composant à l'intérieur de la fenêtre. |
Une Frame lorsque son constructeur la crée est en mode invisible, il faut donc la rendre visible, c'est le rôle de la méthode setVisible ( true) que vous devez appeler afin d'afficher la fenêtre sur l'écran :
Programme Java |
import .*; class AppliWindow { public static void main(String [ ] arg) { Frame fen = new Frame ("Bonjour" ); fen. setVisible ( true ); } } |
Ci-dessous la fenêtre affichée par le programme précédent :
Cette fenêtre est trop petite, retaillons-la avec la méthode setBounds :
Programme Java |
import .*; class AppliWindow { public static void main(String [ ] arg) { Frame fen = new Frame ("Bonjour" ); fen.setBounds(100,100,250,150); fen. setVisible ( true ); } } |
Ci-dessous la fenêtre affichée par le programme précédent :
Pour l'instant nos fenêtres sont repositionnables, retaillables, mais elles ne contiennent rien, comme ce sont des objets conteneurs, il est possible en particulier, d'y inclure des composants.
Il est possible d'afficher des fenêtres dites de dialogue de la classe Dialog, dépendant d'une Frame. Elles sont très semblables aux Frame (barre de titre, cadre, ) mais ne disposent que d'un bouton icône de fermeture dans leur titre : une fenêtre de classe Dialog :
De telles fenêtres doivent être obligatoirement rattachées lors de la construction à un parent qui sera une Frame ou une autre boîte de classe Dialog, le constructeur de la classe Dialog contient plusieurs surcharges dont la suivante :
public Dialog(Frame owner, String title)
où owner est la Frame qui va appeler la boîte de dialogue, title est la string contenant le titre de la boîte de dialogue. Il faudra donc appeler le constructeur Dialog avec une Frame instanciée dans le programme.