Class - Université de Valenciennes

publicité
Cours de JAVA
Programmation avancée en Java
Emmanuel ADAM
Institut des Sciences et Techniques de Valenciennes
Université de Valenciennes et du Hainaut-Cambrésis
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
1
Introduction à JAVA
✎
Présentation
✎
Concepts
✎
Gestion de la mémoire
✎
Gestion de classes
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
2
Présentation de JAVA
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
3
Petite histoire
 1991, chez SUN est créé le langage OAK (pour
interface entre appareil ménagers et ordinateurs)
 1994, Oak se tourne vers Internet et devient Java
 1995, Java est intégré à Netscape
 1998, Version 1.2 de Java
 2000, Version 1.3 de Java
 2002, Version 1.4 de Java
 2004, Version 1.5 de Java / 1.6 en 2006
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
4
Télécharger Java
 Sur son site (http://java.sun.com/), SUN
propose les différents Kits de Développement
Java (JDK)
 SUN propose également une documentation
très complète
 Sur Internet, grand nombre de sources, de
projets open-sources et de documentations [Ex :
"Thinking in Java" de B. Eckel]
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
5
Définition des variables
d'environnement
 Pour compiler en java, il faut définir quelques
variables d'environnement :
 Chemin d'accès aux exécutables. Par exemple :
SET PATH=%PATH%;C:\Sun\SDK\bin
 Chemin d'accès aux librairies. Par exemple :
SET CLASSPATH=.;C:\Sun\SDK\lib
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
6
Les concepts de JAVA
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
7
La Compilation & JAVA
 Le principal atout de JAVA concerne sa portabilité.
 Celle-ci est possible par la notion de ByteCode.
 JAVA ne produit pas un code natif, directement
exécutable.
 JAVA produit un code intermédiaire, le ByteCode,
interprétable par une machine virtuelle.
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
8
La Compilation "classique"
Source A‘
Source B‘
Source A'‘
Source B'‘
Source A''‘
Source B''‘
Compilation & Linkage
sur machine M1
Compilation & Linkage
sur machine M2
Compilation & Linkage
sur machine M3
Exécutable pour
Machine M1
Exécutable pour
Machine M2
Exécutable pour
Machine M3
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
9
La Compilation Java
Source A
Source B
Compilation & Linkage
sur machine M
ByteCode
Exécution sur machine
M1
Exécution sur machine
M2
Exécution sur machine
M3
Interprétation par machine virtuelle (Java Virtual Machine)
spécifique au système d'exploitation
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
10
Code natif vs ByteCode
 (+) rapidité
d'exécution
 (-) source pas
toujours portable
 (-) recompiler pour
changer de système
 (+) source portable
 (+) Bytecode portable
 (-) moins rapide car
interprété
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
11
Source portable
 Les types primitifs sont totalement spécifiés.
 Ils ne dépendent pas de l'architecture de la
machine :
 Les entiers, réels, etc... sont toujours définis sur le même
nombre de bits.
 Génération du ByteCode par le compilateur javac
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
12
Gestion de la mémoire
 En JAVA, tout est objet.
 A chaque objet créé, une zone mémoire est
dynamiquement allouée
 On ne peut détruire explicitement les objets
 Dès qu'un objet n'est plus utilisé (sortie de boucle,
...), il est détruit.
 Le Garbage Collector (ramasse-miettes) se charge
de récupérer la mémoire.
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
13
Exemple de compilation
Hello.java
public class Hello
{
public static void main(String args[])
{
System.out.println("Hello !!!");
}
}
Source
ByteCode
Hello.class
C:\Java>javac Hello.java
Êþº¾ ()V (Ljava/lang/String;)V ([Ljava/lang/String;)V <init>
Code Hello
Hello !!!
Hello.java LineNumberTable Ljava/io/PrintStream;
SourceFile java/io/PrintStream java/lang/Object
java/lang/System main out println !
*· ±
%
² ¶ ±
C:\Java> java Hello
Hello !!!
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
14
Gestion de la mémoire en JAVA
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
15
Ramasse-Miettes
 Ressource mémoire limitée
 Gérer la mémoire ==>
 Ne pas libérer une zone mémoire utilisée par un objet
 Ne pas bloquer une zone mémoire libérée par un objet
détruit
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
16
Ramasse-Miettes
 Perte de mémoire :
 Fuites graves (hard leaks) : inexistence de système de
nettoyage
 Géré par le GC -Garbage Collector la surveillance de l'utilisation des objets,
 la détermination des objets devenus inutiles,
 la récupération des ressources libérées.
 Fuites légères (soft leaks) : un programme ne libère pas
la mémoire d'objets inutilisés
 À gérer par à la programmation
 ob = null; signale l'abandon de l'objet ob
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
17
Fonctionnement
de la Gestion de la mémoire
 La Machine Virtuelle Java (JVM) surveille le nombre nb
de références à chaque objet.
 nb=0 ==> objet inutilisé ==> libérer mémoire
 Le processus GC est lancé périodiquement de façon
asynchrone
 Le GC lance la méthode finalize() de chaque
objet non référencé
 Le programme peut terminer avant que le GC ne soit
lancé
 Impossibilité de prévoir le lancement du GC
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
18
Ramasse-Miettes Synchronisé
 Possibilité de lancer explicitement le GC :
System.gc();
 Appel demandé, non lancé immédiatement
 Indiquer à la JVM le passage en mode totalement
synchrone :
 java -noasyncgc monProg
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
19
Exemple de GC 1/2
public class PersonneF {
String nom, prenom;
static int nb = 0;
int no = 0;
PersonneF(String _nom, String _prenom) {
nom = _nom;
prenom = _prenom;
no = ++nb;
}
}
public void finalize() {
System.out.println("fin de l'objet Personne " + no);
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
20
Exemple de GC 2/2
public class TestPersonneF
{
TestPersonneF(){}
fin de l'objet
fin de l'objet
fin de l'objet
void go(int nb)
fin de l'objet
{
fin de l'objet
for(int i=0; i<nb; i++)
fin de l'objet
PersonneF p = new PersonneF("a"+i, "aa"+i);
fin de l'objet
}
fin de l'objet
fin de l'objet
public static void main(String args[])
fin de l'objet
{
Personne
Personne
Personne
Personne
Personne
Personne
Personne
Personne
Personne
Personne
10
9
8
7
6
5
4
3
2
1
int nb = 10;
if (args.length == 1) nb = Integer.parseInt(args[0]);
TestPersonneF tp
tp.go();
System.gc();
}
= new TestPersonneF();
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
21
Finalisation d'un objet
 Si finalize() est définie, elle est automatiquement
appelée par un thread spécialisé (Finalizer)
 Intérêt : terminer proprement un objet
 Le sauvegarder,...
 Ou le raccrocher à une référence !
 Attention : finalize() appelée 1 seule fois par objet
 Lancer la finalisation avant le GC :
 System.runFinalization();
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
22
Informations sur la mémoire
 long taille = Runtime.getRuntime().totalMemory();
retourne la taille totale de la mémoire de la machine
virtuelle java
 long taille = Runtime.getRuntime().freeMemory();
retourne la quantité de mémoire libre du système
 long taille = Runtime.getRuntime().maxMemory();
retourne la quantité maximale de mémoire utilisable
par la JVM
 Nombres en octets
 Augmenter la taille de la mémoire virtuelle :
-Xmx512M MonProg
 java
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
23
Eléments de base de JAVA
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
24
Tout est Objet (ou presque...)
 Tous les éléments en JAVA dérivent de la
classe Object.
 Tous sauf les primitives (8 en tout)
représentant des types simples.
 A chaque type de primitive correspond une
classe d'objet.
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
25
Les primitives : des types simples
Nom
Taille
Minimum
boolean
1 bit
false
true
Boolean
char
16 bits
Unicode 0
Unicode 216-1
Character
byte
8 bits
-128
127
Byte
short
16 bits
-215
215-1
Short
int
32 bits
-231
231-1
Integer
long
64 bits
-263
263-1
Long
float
32 bits
(+/-)1.4 10-45
(+/-)3.4 1038
Float
double
64 bits
(+/-)4.9 10-324
(+/-)1.8 10308
Double
void
-
-
Void
-
Maximum
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
Classe
26
Les objets simples
 Tout objet Java hérite de la classe Object :
Object
Boolean
Byte
Character
Short
Number
Integer
Void
Long
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
Float
Double
27
Primitives <-> Objets
 Passer d'une primitive à l'objet correspondant :
int i = 5;
Integer obj = new Integer (i);
 Dans la classe Number sont définies les méthodes
de conversion intValue, doubleValue, floatValue, ...
int j = obj.intValue();
 Dans la classe Object est définie la méthode
toString convertissant un objet en chaîne.
Cette fonction est surchargée dans les classes
d'objets numériques.
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
28
Auto(un)boxing :
Primitives <-> Objets implicite
 Passer d'une primitive à l'objet correspondant :
double d1 = 5.1;
Double od1 = d1; Double od2 = 5.3;
 Passer d'un objet à la primitive correspondante :
double d3 = od2;
 Attention au réel simple précision :
Float f = 5.7f;
 Attention au coût de création d'objets
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
29
Exemples de conversions
public class TestNum
{
public static void main(String arg[])
{
double d1 = 5.1; // d1 est un réel double précision
Double od1 = new Double(d1); // objet Double de la valeur de d1
Double od2 = 5.2; // objet Double de valeur 5.2
double d2 = od1.doubleValue();
// définition d'une primitive de la valeur de od1
double d3 = od1; // définition d'une primitive de la valeur de od1
System.out.println(" d1 , od1 , od2 , d2 , d3 ");
System.out.println("" + d1 + " , " + od1 + " , " + od2 + " , " + d2 + " , " + d3);
}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
30
Les Tableaux
 Un tableau en Java est un type d'objet simple
(il ne contient que l'attribut length).
 Tableau simple : int tab [] = new int [10];
 Tableau multi-dimensionnel :
double cube[][][] = new double[3][3][3];
 Initialisation : int tab[] = {1, 2, 3, 4, 5};
 Création et Passage de tableau en argument :
afficheTab(new int[]{1,2,3});
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
31
Les opérateurs (cf. C++)
 Arithmétiques :
pour tout nombre x, on peut écrire :
x++; x--; ++x; --x; x+=2; x-=2; x*=2; x/=2;
x%=2 (x = x modulo 2)
 Logiques : pour tout booléen x et y,
non x  !x
x et y  x & y ou x && y
x ou y  x | y ou x || y
x ou exclusif y  x ^ y
(test économe)
(test économe)
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
32
Structures de contrôle
 Les structures de contrôle utilisées en Java
sont fortement inspirées de celles du langage
C ou C++ :
 if ; else ; while ; do ; for ; break ; goto
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
33
Branchement conditionnel (1/2)
 Si ... Alors ... Sinon
if (test)
{
action1_si_test_vrai;
action2_si_test_vrai;
}
else
{
action1_si_test_faux;
action2_si_test_faux;
}
 Le test est de la
forme :
a ; !a ; a & b ; a & !b ;
x<y ; x == y; x != y ; ...
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
34
Branchement conditionnel (2/2)
 Branchement selon un choix multiple :
switch (expression)
{
case valeur_1 : actions; break;
case valeur_2 : actions; break;
case valeur_3 : actions; break;
default : actions si valeur inconnue;
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
35
Boucle "Tant que"
 while (test)
{
actions;
}
 do
{
actions;
}
while (test);
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
36
Boucle "Pour"
 int i;
for(i=0; i<5; i++) // ou for(int i=0; i<5; i++)
{
actions;
}
 int add(int ... tab)
{
int som=0;
for (int val : tab)
som += val;
return x;
}
 ...
int res = add(15,22,13,64);
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
37
Sorties de boucles
 L'instruction break permet de sortir d'une
boucle avant sa fin "normale".
 L'instruction continue passe le reste de la
boucle, mais n'en sort pas.
 L'instruction goto label subsiste encore. Le
label doit alors être défini (et suivi de : ).
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
38
Programmation Objet en JAVA
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
39
Concept Objet : rappels
 Tout objet dérive d' (instancie) une classe
 Une classe est composée de membres
 Les membres sont :
 des attributs (champs), définissant l’état d'un
objet,
 des méthodes (fonctions, procédures) agissant
sur ou en fonction des attributs,
 un ou des constructeurs, initialisant l'objet.
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
40
Exemple de classe
La classe suivante représente une personne:
Nom de la classe commençant par une
class Personne
{
majuscule
String nom, prenom;
int age;
constructeur
Personne()
Attributs
{
nom = new String("");
prenom = new String("");
age = 18;
méthode
}
void affichePersonne()
{
System.out.println(prenom + " " + nom + ", age : " + age);
}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
41
Exemple d'utilisation d'une classe
class Personne
C:\> javac TestPersonne.java
{…}
C:\> dir *.class
TestPersonne.class
Personne.class
public class TestPersonne
{
C:\> java TestPersonne
public static void main(String args[])
{
Personne p1 = null;
Personne p2 = new Personne();
System.out.println(p1);
System.out.println(p2);
p2.affichePersonne();
p1.affichePersonne();
}
}
Classe@adresse mémoire virtuelle
null
Personne@ea2dfe
, age : 18
Exception in thread "main" java.lang.NullPointerException
at TestPersonne.main(TestPersonne.java:26)
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
42
Utilisation des Objets en Java
 En Java, on manipule des références aux objets,
// construction d'un objet Personne, f1 reçoit son adresse en mémoire virtuelle
Personne f1 = new Personne();
f1.nom = "Simon";
// f2 reçoit la valeur de f1, et donc pointe vers le même objet
Personne f2 = f1;
System.out.println(f1.nom + "-" +f2.nom);
//  Simon – Simon
f2.nom = "hello";
System.out.println(f1.nom + "-" +f2.nom);
//  hello – hello
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
43
Objets anonymes

Il n’est pas nécessaire de donner un nom à un objet:
…
public class TestPersonne
{
public static void main(String args[])
{
Personne [] tableau = new Personne[5];
for (int i=0; i<5; i++)
{
tableau[i] = new Personne ();
tableau[i].age += i;
}
for (int i=0; i<5; i++)
tableau[i].affichePersonne();
}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
,
,
,
,
,
age
age
age
age
age
:
:
:
:
:
18
19
20
21
22
44
Héritage
 En java,
Si une classe A hérite d'une classe B,
elle possède tous les attributs et méthodes de
B non privés
 Notation :
class Animal {...}
class Hamster extends Animal {...}
P a s d ' h é r i t a g e m u l t i p l e
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
45
Héritage : généricité
et surcharge (1/4)
 Une classe fille peut surcharger une méthode
d'une classe mère
 L'objectif de l'héritage est la généricité :
appliquer le même schéma d'actions à des
objets de type différents
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
46
Héritage : généricité
class Animal
{
String nom;
int nb_pattes;
Animal()
{
nom = new String("");
nb_pattes = 0;
}
void affiche()
{
System.out.println("Animal : " + nom + ",
nb de pattes = " + nb_pattes);
}
}
et surcharge (2/4)
public class TestAnimaux
{
public static void main(String args[])
{
Animal a = new Animal();
Hamster h = new Hamster();
a.nom = "ani";
h.nom = "ham";
a.affiche();
h.affiche();
}
}
class Hamster extends Animal
{
Animal : ani, nb de
String couleur_pelage;
Hamster()
Hamster : ham, nb
{
nb_pattes = 4;
Animal : ani, nb de
couleur_pelage = "gris";
}
Hamster : ham, nb
void affiche()
{
System.out.println("Hamster : " + nom + ",
nb de pattes = " + nb_pattes + ",
couleur = " + couleur_pelage);
}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
Animal tab[] = {a, h};
tab[0].affiche();
tab[1].affiche();
pattes = 0
de pattes = 4, couleur = gris
pattes = 0
de pattes = 4, couleur = gris
47
Héritage : généricité
et surcharge (3/4)
 Généricité = utiliser le même code sur tous types
d'objet
 Les objets Java héritent tous de la classe Object
 => utiliser le type Object et le "casting"
 Rq. : instanceof permet de retrouver la classe
d'origine d'un objet
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
48
Héritage : généricité
et surcharge (4/4)
Exemple : un tableau de 4 objets de 2 types différents
Integer i1 = new Integer(11); Integer i2 = new Integer(12);
Personne p1 = new Personne(); Personne p2 = new Personne();
p1.nom = "Nicolas"; p2.nom = "Jose";
Object tab [] = {i1, p1, i2, p2};
for(int i=0; i<4; i++)
{
Object o = tab[i];
if (o instanceof Integer)
System.out.println("Integer, val = " + (Integer)o );
else if (o instanceof Personne)
{
Personne f = (Personne )o;
System.out.println(" Personne, nom = " + f.nom );
}
else System.out.println("Objet indéterminé" );
}
casting
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
49
Comparer les objets en Java (1/2)
 Le test == ne compare que les valeurs des
références
Personne p1 = new Personne(); Personne p2 = new Personne();
p1.nom = "Samia" ; p2.nom = "Samia" ;
System.out.println(p1 == p2);
// false
System.out.println(p1 == p1);
// true
 Solution : surcharger la méthode equals de
la super class Object
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
50
Comparer les objets en Java (2/2)
Il faut comparer chaque champs de la classe
class Personne // extends Object par défaut
{....
public boolean equals(Object o)
{
boolean rep;
Personne p = (Personne)o;
rep = nom.equals(p.nom) && prenom.equals(p.prenom) && age==p.age;
return rep;
}
}
public class TestEgalite
{
public static void main(String args[])
{
Personne p1 = new Personne(); Personne p2 = new Personne();
p1.nom = "Samia" ; p2.nom = "Samia" ;
System.out.println(p1 == p2);
System.out.println(p1.equals(p2));
}
false
true
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
51
Protection des attributs et méthodes
 Un attribut ou une méthode précédé de
 private n'est accessible que par sa classe,
 protected est accessible aux sous-classes et aux
classes voisines,
 public est accessible à toutes classes.
 private protected n’est plus utilisé,
 Par défaut : protected.
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
52
Exemple de protection
La classe suivante représente une personne:
class PersonneP
{
public String nom, prenom; // accessible par toutes les classes
private int noSecu;
// accessible par cette classe uniquement
int noTel; //accessible par cette classe et classes voisines
int age; //accessible par cette classe et classes voisines
Personne()
{
nom = new String("");
prenom = new String("");
age = 18; noSecu = 0; noTel = 0;
}
public void affichePersonne()
// toutes les classes peuvent appeler cette méthode
{
System.out.println(prenom + " " + nom + ", age : " + age);
}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
53
Exemple d'utilisation d'attributs
protégés
class PersonneP
{…}
public class TestPersonneP
{
public static void main(String args[])
{
PersonneP p = new PersonneP();
System.out.println(p);
p.affichePersonne();
p.noSecu = 5;
}
>javac TestPersonne.java
TestPersonne.java:26: noSecu has private access in Personne
p.noSecu = 5;
}
^
1 error
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
54
Membres particuliers : Constructeurs
 Un constructeur est appelé automatiquement à la
création de l'objet
 Le constructeur permet d'initialiser un objet
 Le constructeur d'une classe porte le nom de cette
classe. Exemple :
class Fenetre
{
String nom;
Fenetre () {nom = "";}
// constructeur par défaut
//Fenetre (String nom) {this.nom = nom;}
Fenetre (String _nom) {nom = _nom;}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
55
Membres particuliers : This
 Le champ this d'une classe se réfère à l'instance de l'objet en cours de traitement.
 Il peut être utilisé :
- Dans un constructeur,
- Pour passer une référence à l'objet
-
class Fenetre
{ ObjetGraphique og = null; …
public void affiche()
{
og.afficheGraphique( this );
}…
}
- Pour retourner une référence à l'objet
-
class Fenetre
{ ....
Fenetre changeNom(String nom2)
{
nom = nom2;
return this;
}
}
- Pour lier deux objets
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
56
Héritage et constructeurs
 Si la classe A hérite de la classe B, le
constructeur de A fait automatiquement appel
au constructeur par défaut de B.
 super permet de choisir le constructeur de la
classe mère :
class B
{ ...
B(){...}
B(int i){...}
}
class A extends B
{ ...
A() {...}
A(int i, int j) {super(i); ...}
A(int i, int j, int k) {this(i,j); ...}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
57
Appel de la méthode initiale
 Soit la classe A héritant de la classe B,
A surchargeant affiche() de B
 A peut appeler affiche() de B par :
 super.affiche();
 On ne peut appeler la méthode de la super
super classe
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
58
Autres mots-clés : final
 final définit :
 un attribut invariable,
dont la valeur ne peut être modifiée que par le constructeur
final int noSecu;
 une méthode qui ne peut être surchargée,
final void affichePersonne(){…}
 une classe qui ne peut être héritée.
final class Personne {…}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
59
Autres mots-clés : static
(1/2)
 static définit un membre commun à toutes les
instances de la classe
 On parle de
membre de classe
par opposition à membre d'instance
 Une variable de classe est indépendante de
l'objet, elle existe dès le premier appel à la
classe.
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
60
Autres mots-clés : static
(2/2)
 Seule une méthode de classe peut utiliser des
variables de classe
 Une méthode de classe ne peut être surchargée
dans les sous-classes
 Utilisation des membres de classe :
 compteur d'objet,
 optimisation (définition de constante),
 définition de librairies, …
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
61
Utilisation de static (1/4)
class Personne
{
String nom, prenom;
static int nbPersonnes = 0;
final int noPersonne;
// définition de la variable statique
Personne(String _nom, String prenom)
{
nom = _nom;
this.prenom = prenom;
noPersonne = ++nbPersonnes;
}
}
// constructeur avec paramètres
public String toString()
// surcharge de la méthode héritée de Object
{
return (prenom + " " + nom + ", no personne = " + noPersonnes );
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
62
Utilisation de static (2/4)
public class TestPersonne
{
public static void main(String args[])
{
Personne p1 = new Personne("aa", "a");
// Personne.nb_personne
Personne p2 = new Personne("bb", "b");
// Personne.nb_personne
Personne p3 = new Personne("cc", "c");
// Personne.nb_personne
Personne p4 = new Personne("dd", "d");
// Personne.nb_personne
Personne p5 = new Personne("ee", "e");
// Personne.nb_personne
System.out.println(p1);
System.out.println(p2);
System.out.println(p3);
System.out.println(p4);
System.out.println(p5);
a aa, no personne = 1
}
}
b bb, no personne = 2
1
2
3
3
3
c cc, no personne = 3
d dd, no personne = 4
e ee, no personne = 5
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
63
Utilisation de static (4/4)
class Personne
{
…
}
static int retourneNbPersonnes()
{
return (no_personne);
}
public class TestPersonne
{
public static void main(String args[])
{
Personne p1 = new Personne("aa", "a");
Personne p2 = new Personne("bb", "b");
nombre d'objets Personne crees = 2
// nb_personne  1
// nb_personne  2
int nb_personnes = Personne.retourneNbPersonnes();
}
}
System.out.println("nombre d'objets Personne crees = " + nb_personnes);
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
64
Autres mots-clés : abstract
(1/2)
 abstract associé à une méthode permet de ne
pas lui donner de corps.
 Si une méthode est abstraite,
sa classe doit être définie comme abstraite.
 Une classe abstraite ne peut être instanciée.
 L'abstraction : définir un moule général pour
les classes dérivées.
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
65
Autres mots-clés : abstract (2/2)
abstract class Animal
{
}
String nom;
int nb_pattes;
Animal()
{
nom = new String("");
nb_pattes = 0;
}
abstract void affiche();
class Mamifere extends Animal
{
Mamifere()
{
nb_pattes = 4;
}
void affiche()
{
System.out.println("Mamifere : " + nom +
", nb de pattes = " + nb_pattes);
}
}
public class TestAnimaux
{
public static void main(String args[])
{
Mamifere m = new Mamifere();
m.nom = "mami";
m.affiche();
}
}
Mamifere : mami, nb de pattes = 4
// Animal a = new Animal(); n'est pas possible !!!
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
66
Interface : une "classe vide"
 Une interface est une classe :
 ne contenant que les entêtes de méthodes (public par
défaut)
 ne contenant que des attributs constants (de type static
et final).
 Notation :
interface EtreVivant
{
String type = "etre vivant";
d'initialiser l'attribut
void naitre();
}
// obligation
class Animal implements EtreVivant
{… }
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
67
Implémentations multiples
 Pas d'héritage multiple en java, mais possibilité d'implémentation multiple:
 Notation :
interface EtreVivant
{…}
interface EtreMortel extends EtreVivant
{
}
void mourir();
interface EtreSpirituel
{
void philosopher();
}
class Animal implements Etre_vivant, EtreMortel
{…}
class EtreHumain extends Animal implements EtreSpirituel { … }
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
68
Interface pour regrouper les constantes
 Les attributs des interfaces sont statiques et finaux par défaut
  possibilité de créer des groupes de constantes
interface Couleur
{
int BLANC = 999, NOIR = 000, GRIS = 555,
BLEU = 900, ROUGE = 090, VERT = 009;
}
public class TestCouleur
{
public static void main(String arg[])
{
}
}
int couleur_a = Couleur.BLEU;
System.out.println(couleur_a);
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
// ==> 900
69
Enumérations
 Possibilité de définir des énumération sans interface :
enum nom {VALEUR1, ...}
enum Couleur {BLANC, NOIR, GRIS, BLEU, ROUGE, VERT};
public class TestCouleur
{
public static void main(String arg[])
{
}
}
Couleur a = Couleur.BLEU;
System.out.println(a); // ==> BLEU
 Utilisable dans les switch :
Couleur c = Couleur.BLANC;
switch (c)
{
case(BLEU): System.out.println("c'est bleu");
break;
case(BLANC): System.out.println("c'est blanc");
break;
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
70
Classes internes
 Pour grouper les classes logiquement rattachées
 Il est possible d'imbriquer
 des classes et interfaces dans des classes
 des interfaces dans des interfaces
 Les classes internes peuvent être héritées
 Une classe interne peut accéder à tous les membres
même private la classe mère
 Une classe interne ne peut définir de membre statiques
hors finaux
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
71
Classes internes
 Possibilité d'imbrication sur plusieurs niveaux
 Il est possible de distinguer les variables de même nom
entre classe interne et externe
classeExterne.this.nomVariable
 Une classe interne peut être statique
 Pour instancier une classe interne, il faut d'abord
instancier la classe contenante
ClasseContenante cc = new ClasseContenante();
ClasseContenante.ClasseInterne obj = cc.new ClasseInterne();
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
72
Classes internes : exemple
1/3
class Formation
{
String nom;
String type;
Etudiant [] tabEtu = new Etudiant[10];
private int index = 0;
Formation() { nom = ""; type = "";}
Formation (String nom, String type) { this.nom = nom; this.type = type;}
int nbEtudiants() { return index; }
void ajouteEtu(String nom, String prenom)
{
Etudiant e = new Etudiant(nom, prenom);
e.ajoute();
}
…
public String toString()
{
String chaine = "";
for(int i=0; i<index; i++)
chaine = chaine + tabEtu[i] + "\n";
return chaine;
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
73
Classes internes : exemple
….
2/3
class Etudiant
{
String nom, prenom;
Etudiant() {nom = ""; prenom = "";}
Etudiant(String nom, String prenom)
{this.nom = nom; this.prenom = prenom;}
void ajoute()
{
if (index<10)
{
tabEtu[index] = this; // la classe interne a accès à tous les éléments
index++;
// de la classe conteneur, même privés
}
}
public String toString()
{
String formation = Formation.this.nom;
return (formation + " : " + nom + " " + prenom);
}
}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
74
Classes internes : exemple
public class TestFormation
{
public static void main(String args[])
{
Formation f = new Formation("L3_Info", "bac+3");
3/3
%javac TestFormation.java
%ls *.class
Formation.class Formation$Etudiant.class
TestFormation.class
f.ajouteEtu("alain", "zouave");
f.ajouteEtu("ben", "yolta");
System.out.println(f);
}
}
Formation.Etudiant e = f.new Etudiant("cloe", "xerty");
System.out.println(e);
L3_Info : alain zouave
L3_Info : ben yolta
L3_Info : cloe xerty
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
75
Classes locales
 Une classe locale est définie dans une méthode
 Une classe locale accède aux membres de la classe
contenante
 Une classe locale ne peut accéder qu'aux membres de
type final de la méthode englobante
 Une classe locale dans une méthode statique ne peut
accéder qu'aux membres statiques de la classe
contenante
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
76
Classes locales : exemple

int division(int a, final int b)
{
class Verif
{
boolean divOk(){return (b!=0);}
}
Verif v = new Verif();
if(v.divOk()) return a/b;
else return 0;
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
77
Classes anonymes
 Il est possible de créer des classes anonymes
 héritant d’une classe ou implémentant une
interface
 Pour un usage limité à 1 objet, …
interface Professeur
// soit une interface Professeur
{
String getName ();
}
…
Professeur prof = new Professeur()
// création dynamique d’une classe
{
// implémentant Professeur
private String nom = "Adam";
// et création de l’objet prof de
public String getName () { return nom; } // cette classe anonyme.
};
System.out.println(prof.getName()); // utilisation classique de l’objet
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
78
Classes anonymes
 Une classe anonyme peut accéder aux membres de la
classe contenante
 Une classe anonyme ne peut créer de nouveau
constructeur, elle en hérite
 Possibilité de passer des paramètres au constructeur :
void testAnonyme()
{
PersonneF p = new PersonneF("ab","cd", null){
public String toString()
{
return(nom.toUpperCase() +" " + prenom );
}};
System.out.println(p);
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
79
Classes anonymes : Exemple
import java.awt.*;
import java.awt.event.*;
public class TestFenetre
{
public static void main(String arg[])
{
MaFenetre mf = new MaFenetre();
mf.ajoutGestionFenetre();
mf.show();
}
}
class MaFenetre extends Frame
{
MaFenetre()
{
this.setTitle("exemple de classe anonyme");
this.setBounds(10,10,400,50);
}
public void ajoutGestionFenetre()
{
MaGestionFenetre mgf = new MaGestionFenetre();
addWindowListener(
new WindowAdapter()
class MaGestionFenetre
extends
WindowAdapter
{
{
public
void
public
voidwindowClosing(WindowEvent
windowClosing(WindowEventevt)
evt)
{ {
System.out.println("Fermeture
de de
la fenetre");
System.out.println("Fermeture
la fenetre");
System.exit(0);
System.exit(0);
} }
});
}
}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
80
Les paquetages
 Un paquetage définit un espace nommé pour un groupe de
classes
 Les paquetages sont organisés en hiérarchie
 Importation d'une classe ou de classes d'un paquetage :
import
import
import
import
NomClasse;
nomPaquetage.NomClasse;
nomPaquetage1.nomPaquetage2.NomClasse;
nomPaquetage.*;
 Le caractère * ne porte que sur les classes d'un
paquetage, pas sur ses sous-paquetages
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
81
Les paquetages
 Définir un paquetage, ligne :
package nomPaquetage;
à placer en tête de fichier source
 Les fichiers d'un paquetage doivent se trouver dans le
répertoire portant le nom du paquetage
 Possibilité de création automatique des répertoires pour
les classes compilées :
javac -d repDesClasses MonProg.java
 Attention à la portée des membres de classes, seuls les
membres publiques sont accessibles entre paquetages
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
82
La classe Package
 La classe Package représente un paquetage Java
Package paquet = Package.get("java.nio.channels");
 Pour obtenir tous les packages en cours :
Package[] paquets = Package.getPackages();
 Quelques informations
getImplementationTitle(); getSpecificationTitle();
getImplementationVendor(); getSpecificationVendor();
getImplementationVersion(); getSpecificationVersion();
...
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
83
La classe Package
 Compatibilité :
 Vérifier si un paquetage est compatible avec une
version prévue :
if (paquet.isCompatibleWith("1.6.1"))
{ ....... }
 Sécurité :
 Vérifier si un paquetage est scellé : toutes les classes
du paquetage proviennent du même fichier jar
if (paquet.isSealed()){ ....... }
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
84
Introspection
 L'introspection permet de gérer dynamiquement des classes :
 Lister les membres
 Créer une instance d'une classe non importée
 La classe Class permet de créer des objets descripteurs de
classe
 La JVM créé des objets Class pour chaque classe utilisée dans
un programme
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
85
Introspection
 Récupérer le descripteur d'une classe chargée :
javax.swing.JFrame fen = new javax.swing.JFrame();
Class classeJFrame = fen.getClass();
 Charger une classe dynamiquement
Class classeChargee = Class.forName("Fenetre");
Class classeChargee = Class.forName("javax.swing.JFrame");
 Attention : la classe à charger doit être compilée et accessible : se trouver
dans le classpath
 Récupérer le nom : getName()
 Possibilité de récupérer un tableau !
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
86
Introspection
 Récupérer tous les éléments d'un descripteur de classe :
Field[] getDeclaredFields(); Method[] getDeclaredMethods();
Constructor[] getDeclaredConstructors();
 Récupérer les éléments publiques d'un descripteur de classe :
Field[] getFields(); Method[] getMethods();
Constructor[] getConstructors();
 Possibilité de récupérer les modificateurs
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
87
Introspection
 Création d'un objet et invocation d'une méthode :
1. définir un descripteur de classe
2. Récupérer les informations sur les constructeurs et membres
3. Choisir un constructeur du descripteur de classe
4. Créer une instance à partir du constructeur
5. Choisir une méthode du descripteur de classe
6. Invoquer la méthode sur l'instance créée
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
88
Introspection
 Création d'un tableau d'objets :
Object tab =
Array.newInstance(Class.forName("java.lang.String"), 20);
int[] taille = {3,4,7};
Object cube =
Array.newInstance(Class.forName("Personne"), taille);
 Ajout d'un élément :
Array.set(tab, 0, "bonjour...");
 Obtenir un élément:
String mot = (String)Array.get(tab, 0);
 Obtenir la taille: int taille = Array.getLength(tab);
 Obtenir les tailles : int m=Array.getLength( Array.get(tab,0));
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
89
Création dynamique d'instance: exemple
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class TestClass
{
public static void main(String args[])
{
try
{
Class c = Class.forName("Personne");
//recherche de la classe Personne
Class typeParamCons[] = {String.class, String.class};
// recherche du constructeur avec
Constructor ctor = c.getDeclaredConstructor(typeparamCons);
// 2 paramètres String
Object paramCons[] = {"benoit", "zed"};
// appel du constructeur avec
Object personne = ctor.newInstance(paramCons);
// 2 paramètres
Method m = c.getMethod("affiche", null);
// recherche de la méthode
affiche
m.invoke(personne, null);
// appel de cette méthode
}
catch(Exception e)
{System.out.println("Erreur de recherche de classe : " + e);}
}
}
Emmanuel ADAM – Université de Valenciennes et du Hainaut Cambrésis
90
Téléchargement