Seance1Java

advertisement
LANGAGE JAVA
2008-2009
Prof. HAMID ZOUAKI
PRESENTATION GENERALE
Langage récent
Orienté objet dérivé du C++, répond aux
trois principes:
Encapsulation
Polymorphisme
Héritage
Multi plateformes
Bibliothèques de classes très riches
Mécanisme de gestion des erreurs performant
Applets et Applications
La machine virtuelle
Java est un langage qui doit être compilé et
interprété.
Dans une première phase on compile un programme
(un ou plusieurs fichiers source .java) en fichiers
.class. Le compilateur génère un fichier .class pour
chacune des classes définies dans le(s) fichier(s)
.java.
L'ensemble des fichier .class est ensuite interprété
par la Machine Virtuelle Java pour exécuter le
programme (seule la JVM dépend du système).
La machine virtuelle
Caractéristiques
Long à démarrer
Gourmand en mémoire
Rapide une fois initialisé (JIT)
Conséquences
Java beaucoup utilisé coté serveur
Très bon langage pour les couches hautes (IHM, Web
…etc)
Non approprié pour couches basses (calcul
scientifique)
La machine virtuelle
Pourquoi ne pas interpréter directement le programme
Java ?
Les fichiers .class contiennent du byte code, une sorte de code
machine Java. L'interpréteur exécute beaucoup plus rapidement
ce byte code que les fichiers sources .java.
Seuls les fichiers .class sont nécessaires à l'exécution d'un
programme Java. Ils contiennent du code machine et ne
peuvent donc pas être lus par des tiers, protégeant ainsi le code
source.
Etant compilés, les fichiers .class sont de taille plus petite que
le code source Java ; ceci est un argument important pour
transférer les programmes sur Internet.
Chaque fichier .class décrivant une classe d'objet, une même
classe peut être utilisée par différents programmes sans que
cette classe ne soit dupliquée dans chacun des programmes.
Particularités
Simple
Utilisation transparente des pointeurs
Gestion automatique de la mémoire (Garbage Collector)
Robuste
Nombreux contrôles à la compilation
Gestion des exceptions
Contrôle du débordement de bornes
Multithreads
Contrôle de la synchronisation des processus Particularités
Sécurisé
Vérification du byte code par la JVM
Gestion des pointeurs: évite l’accès à certaines zones mémoires
Sauf paramétrage, une applet ne peut pas accéder au disque
dur
Introspection
Permet de déterminer les variables et méthodes d’une classe
sans disposer du code source
API
java.lang, java.io
Fonctionnalités
Types de données et
entrées sorties
Java.awt
graphisme et multi
fenêtrage
Java.swing
Graphisme 2D et IHM
JDBC
Accès aux bases de
données relationelles
Thread
multithreading
Servlet/JSP
Aspect web
Java 3D
Graphisme 3D
…
API Java
Un grand nombre de classes prédéfinies
et standardisées (> 6000)
Classes conçues pour fonctionner sur
toute plate forme
Gratuit
Principes de la POO
Toute chose est un objet
penser à un objet comme à une variable améliorée : il stocke des
données, mais on peut « effectuer des requêtes » sur cet objet, lui
demander de faire des opérations sur lui-même.
En théorie, on peut prendre n'importe quel composant conceptuel du
problème qu'on essaye de résoudre (un chien, un immeuble, un service
administratif, etc...) et le représenter en tant qu'objet dans le
programme.
Un programme est un ensemble d'objets qui
communiquent entre eux en s'envoyant des messages.
Pour qu'un objet effectue une requête, on « envoie un message » à cet
objet.
Un message est un appel à une fonction « méthode « appartenant à
un objet particulier.
Principes de la POO
Chaque objet a son propre espace de mémoire composé d'autres
objets:
On peut ainsi cacher la complexité d'un programme par la simplicité des objets
mis en œuvre.
Chaque objet est d'un type précis:
Chaque objet est une instance (ou une réalisation) d'une classe.
« classe » a une signification proche de « type ».
Tous les objets d'un type particulier peuvent recevoir le même
message.
un objet de type « cercle » est aussi un objet de type « forme géométrique ».
Un cercle se doit d'accepter les messages destinés aux formes géométriques.
Cela veut dire qu'on peut écrire du code parlant aux formes géométriques qui
sera accepté par tout ce qui correspond à la description d'une forme
géométrique.
Notion de classe
tous les objets, tout en étant uniques, appartiennent à un
ensemble d’objets qui ont des caractéristiques et des
comportements communs
Pour représenter (implémenter) des objets, on dispose de
classes:
chaque objet manipulé est le représentant d’une classe.
Classe = type générique dont les objets sont des instances.
Deux objets sont des instances d’une même classe:
ils partagent une certaine structure et des traitements qu’on
peut leur appliquer. N’empêche qu’ils soient différents l’un de
l’autre.
Notion de classe
Exemple:
Toutes les voitures sont des objets qui ont
4 roues, un volant, un moteur et une carrosserie
Peuvent être mise en marche, stoppées, conduites, repaintes … etc.
Mais,
Certaines voitures ont 3 portes, des moteurs de puissances différentes
… etc.
Tous les objets de type voiture (instance de la classe voiture) ont les
mêmes attributs, mais ces attributs prennent des valeurs différentes.
La classe voiture représente la structure générale que partagent toutes
les voitures.
Notion de classe
Utiliser un objet
Ampoule amp = new Ampoule() ;
amp.Allumer() ;
type
Interface:
Puissance
Ampoule
Allumer
Eteindre
Notion de classe
L'interface précise quelles sont les caractéristiques d’un objet (ici type
et puissance) et quelles sont les opérations que l’on peut effectuer sur
un objet particulier (ici Allumer et Eteindre).
L’interface ne précise pas la manière dont elles sont effectuées (c’est-àdire le code correspondant à l’opération) : c’est le rôle de
l’implémentation.
Du point de vue de la programmation, une classe dispose de fonctions
associées à chaque requête possible (appelée méthodes).
Lorsqu’on effectue une requête particulière sur un objet, ces fonctions
sont appelées: on dit qu'on « envoie un message » à un objet, l'objet
se « débrouillant » pour l'interpréter (exécution du code associé).
Ici, le nom de la classe est Ampoule, le nom de l'objet Ampoule créé
est amp.
D’après l’interface, on peut demander à un objet Ampoule de s'allumer
et de s'éteindre.
Un objet Ampoule est créé en définissant une « référence » (amp)
pour cet objet et en appelant new pour créer un nouvel objet de cette
classe.
Exemple java
Fichier: CompteEnBanque.java
import java.io.*;
import java.util.*;
import java.lang.*;
public class CompteEnBanque {
protected int solde;
/* Constructeur */
public ComptEnBanque()
{
setSolde(0);
}
public void setSolde(int montant)
{
solde= montant;
}
public int getSolde()
{
return solde;
}
public static void main(String[] args)
{
CompteEnBanque cpt = new CompteEnBanque();
Cpt.setSolde(50);
System.out.printn(« solde courant: « + cpt.getSolde() );
}
}
La composition
La réutilisation des classe créées et testées est l’un
des grands avantages des langages orientés objets.
On peut placer un objet d’une classe à l'intérieur
d'une nouvelle classe : c’est ce qu’on appelle « créer
un objet membre ». La nouvelle classe peut être
constituée de n'importe quel nombre d'objets
d'autres types, selon la combinaison nécessaire pour
que la nouvelle classe puisse réaliser ce pour quoi
elle a été conçue.
ce concept est appelé composition (agrégation).
La composition
class Moteur
{
float Cylindree ;
float Puissance ;
void Allumer () ;
void Eteindre () ;
}
class Voiture
{
Moteur m ;
String Marque ;
Color Couleur ;
}
L’héritage
Une fois votre classe créée et testée, il serait dommage de devoir en
créer une nouvelle pour implémenter des fonctionnalités similaires.
Il est plus intéressant de prendre la classe existante, de la cloner et de
faire des ajouts ou des modifications. C'est ce que permet l'héritage.
Avec la restriction suivante : si la classe d’origine ( classe de base ou
classe mère) est modifiée, la classe fille ( classe dérivée, héritée ou
sous-classe) répercutera ces changements.
Les classes Java sont ordonnées dans un arbre d’héritage. Une classe
peut être déclarée comme classe fille en utilisant le mot clef extends.
Une classe fille peut être à nouveau dérivée.
Une classe fille hérite de tous les membres de sa classe mère qui ne
sont pas privés.
L’héritage
Bien que l'héritage puisse parfois impliquer l’ajout de
nouvelles fonctions à l'interface, il existe une autre
manière de différencier la nouvelle classe : changer
le comportement d'une des méthodes existantes de
la superclasse. C’est ce que l’on appelle redéfinir
(ou surcharger) cette fonction.
Pour redéfinir une fonction, il suffit de créer une
nouvelle définition pour la fonction dans la classe
dérivée. C'est comme dire : « j'utilise la même
interface ici, mais je la traite d'une manière différente
dans cette nouvelle classe ».
L’héritage
class Animal {
float poids;
…
void manger() {
….
}
void dormirr() {
….
}
…
}
}
class Mammifère extends Animal {
int rythmeCardiaque;
// herite de poids
…
void respirer() {
…
}
// herite de manger() et dormir()
L’héritage
Un objet de type Mammifère possède à la fois la variable d’instance poids et la méthode
manger().
class Chat extends Mammifère {
boolean poilLong;
// hérite de poids et rythmeCardiaque
…
void ronronner() {
…
}
// redéfinit dormir()
void dormirr() {
….
}
// hérite de manger() et respirer()
}
Chat minou = new Chat();
Animal créature = minou;
Le chat minou peut être affecté à la variable créature de type Animal, car Chat est un type
dérivé de Animal.
créature.dormir(); // c’est la méthode dormir() de Chat qui est appelée.
Le Polymorphisme
Il arrive que l’on veuille traiter un objet non en tant qu'objet de la classe
spécifique, mais en tant qu'objet de sa classe de base. Cela permet d'écrire du
code indépendant des classes spécifiques.
Par exemple pour une forme géométrique, les fonctions manipulent des formes
génériques sans se soucier de savoir si ce sont des ellipses, des rectangles, des
triangles ou même des formes non encore définies.
Toutes les formes peuvent être dessinées, effacées … etc. Ces fonctions
envoient simplement un message à un objet forme, elles ne se soucient pas de
la manière dont l'objet traite le message. Par exemple, on peut dériver une
nouvelle classe de forme appelée « pentagone » sans modifier les
fonctions qui traitent des formes génériques.
Cette capacité à étendre facilement un programme en dérivant de nouvelles
sous-classes est important car il améliore considérablement la conception tout
en réduisant le coût de maintenance.
Exemple
import java.util.*;
class Instrument {
public void play() {
System.out.println("Instrument.play()");
}
public String what() {
return "Instrument";
}
public void adjust() {}
}
class Wind extends Instrument {
public void play() {
System.out.println("Wind.play()");
}
public String what() { return "Wind"; }
public void adjust() {}
}
class Percussion extends Instrument {
public void play() {
System.out.println("Percussion.play()");
}
public String what() { return "Percussion"; }
public void adjust() {}
Exemple
class Stringed extends Instrument {
public void play() {
System.out.println("Stringed.play()");
}
public String what() { return "Stringed"; }
public void adjust() {}
}
class Brass extends Wind {
public void play() {
System.out.println("Brass.play()");
}
public void adjust() {
System.out.println("Brass.adjust()");
}
}
class Woodwind extends Wind {
public void play() {
System.out.println("Woodwind.play()");
}
public String what() { return "Woodwind"; }
}
Exemple
public class Music3 {
static void tune(Instrument i) {
i.play();
}
static void tuneAll(Instrument[] e) {
for(int i = 0; i < e.length; i++)
tune(e[i]);
}
public static void main(String[] args) {
Instrument[] orchestra = new Instrument[5];
int i = 0;
// Upcasting :
orchestra[i++] = new Wind();
orchestra[i++] = new Percussion();
orchestra[i++] = new Stringed();
orchestra[i++] = new Brass();
orchestra[i++] = new Woodwind();
tuneAll(orchestra);
}
}
Exemple
Résultat de l’exécution:
Wind.play()
Percussion.play()
Stringed.play()
Brass.play()
Woodwind.play()
Download