Title: LIP6 cours L3 : POBJ Programmation par Objets en Java
1LIP6 cours L3 POBJ Programmation par Objets
(en Java)
- Olivier Sigaud
- LIP6/AnimatLab
- olivier.sigaud_at_lip6.fr
- 01.44.27.88.53
2Plan du cours 2
- Tableaux dobjets
- Copie d'un objet, superficielle et profonde
- Problèmes de copie
- Passage de paramètres
- Membres statiques
- Conventions
- Quelques exemples de classes du JDK
- Quelques codes utiles
3Tableaux dobjets
4Tableaux d'objets
Allocation dynamique Object
valeurs valeurs new Object5 Attention,
on na pas encore réservé la mémoire pour des
objets contenus dans le tableau
null
valeurs0
valeurs2
null
null
valeurs4
5Tableaux dobjets (2)
Voiture cars
Voiture objet créé avec new
cars0
cars2
Voiture objet créé avec new
cars4
Il faut allouer la place pour les objets
6Tableaux dobjets ce quil faut faire
- Voiture cars
- cars new Voiture5 // allocation de 5
pointeurs sur des Voitures - for (int i0iltcars.lengthi)
-
- carsi new Voiture() //allocation des
Voitures -
7Duplication dobjets, clonage et construction de
copies
8La référence this
- Renvoie une référence sur lobjet courant
- Représente lidentité de lobjet
- Correspond souvent à une adresse en mémoire
- class Genome
- private int nbGenes
- public Genome(int nbGenes)
- this.nbGenes nbGenes
- this.maMethode()
- Gene monGene new Gene(this)
-
9Usage de this
- Cest une valeur qui peut être
- passée en paramètres
- retournée par une méthode
- affectée à une variable
- Par contre, on ne peut pas lui appliquer des
opérations arithmétiques ou logiques (différence
entre référence et pointeur) - Egalité superficielle teste si 2 objets ont la
même identité (i.e. même adresse en Java)
10Copie profonde ou de surface ?
- On peut avoir besoin de créer deux objets
identiques - Veut-on deux références sur le même objet ou deux
objets différents avec les mêmes valeurs ? - Deux télécommandes pour la même télévision, ou
bien deux télévisions de même modèle ? - S'il n'y a qu'une télévision, changer de chaîne
avec une des télécommandes change la chaîne sur
le poste unique...
11 Philosophie de la copie
- En C, on peut manipuler soit lobjet
directement, soit une référence sur un objet - Donc le cas où on duplique lobjet est vu comme
le cas standard, et celui où on a deux références
sur le même objet est lexception - En Java, on ne manipule que des références
- Donc la duplication dobjets est lexception, et
la copie de la référence le cas standard - On duplique très peu dobjets en java
12Copie d'une référence
Voiture objet créé avec new
mavoiture
voiture_2
mavoiture new Voiture() voiture2
mavoiture
13Constructeurs de copies
- Cest un constructeur comme les autres
- Il alloue de la mémoire
- Mais il prend en paramètre un objet du même type
(la source), et il initialise ses propres
attributs aux mêmes valeurs que la source - Inexistant en java on trouve plutôt des
constructeurs de conversion qui prennent en
paramètre un objet dun type proche et le
transforment en objet du type attendu - Ex les collections (transformer une liste en
set) - Introduit ici à des fins pédagogiques
14Constructeur de copie syntaxe
- class Voiture
-
- private int nbPortes
- private double cylindree
- public Voiture(Voiture v)
-
- nbPortes v.nbPortes
- cylindree v.cylindree
-
15Création de la copie
On duplique effectivement lobjet
Voiture objet créé avec new
mavoiture
voiture_2
Voiture objet créé avec new
mavoiture new Voiture() voiture2 new
Voiture(mavoiture)
16Méthode clone()
- Le recours au constructeur de copie pour
dupliquer lobjet est une habitude C - En Java, on préfère utiliser la méthode clone()
- Philosophie différente
- Avec clone(), cest lobjet qui est responsable
de renvoyer sa propre copie - Avec le constructeur de copie, cest la copie qui
se construit à partir dun objet - En particulier pour la copie profonde, préférer
clone(), fournie par les classes du JDK
17clone() on aimerait écrire
- class Voiture
-
- private int nbPortes
- private double cylindree
- public Voiture clone()
-
- Voiture v new Voiture()
- v.nbPortes nbPortes
- v.cylindree cylindree
- return v
-
-
- Mais ce nest pas si simple ?
18clone() ce quil faut écrire (1)
- class Voiture implements Cloneable
-
- private int nbPortes
- private double cylindree
- public Object clone()
-
- Voiture v new Voiture()
- v.nbPortes nbPortes
- v.cylindree cylindree
- return v
-
-
- Car méthode clone() définie dans Object ?
19clone() syntaxe dappel (2)
- class Main
-
- public static void main(String args)
- Voiture v new Voiture()
- Voiture v2 (Voiture) v.clone()
-
-
- Utilisation des mécanismes dhéritage (cast)
- Ces points deviendront plus clairs après le cours
sur lhéritage
20clone() solution (lourde mais propre)
- class Voiture implements Cloneable
-
-
- public Voiture cloneAsVoiture()
- return (Voiture) clone()
-
- public Object clone()
-
-
- Voiture v cloneAsVoiture() //Permet de
cacher le cast
21clone() le pire
- On ne peut pas écrire de clone() qui fasse des
copies profondes pour une collection dobjets de
la classe Object - Raison clone() est déclarée protected dans la
classe Object - Problèmes entre classes génériques et collections
- On approfondira ça plus tard
22Exercice
- Soit la classe Voiture qui contient les attributs
suivants - class Voiture
-
- private Moteur moteur
- private int nbportes
- private double cylindree
-
-
- Moteur est une autre classe
- Ecrire le constructeur de copie de la classe
Voiture
23Erreur à ne pas commettre
- class Voiture
-
- private Moteur moteur
- private int nbPortes
- private double cylindree
- public Voiture(Voiture v)
-
- moteur v.moteur
- nbportes v.nbPortes
- cylindree v.cylindree
-
24Erreur résultat
Voiture objet créé avec new
mavoiture
Moteur objet créé avec new
voiture_2
Voiture objet créé avec new
mavoiture new Voiture() voiture2 new
Voiture(mavoiture)
25Construction correcte de la copie
- Chaque constructeur de copie doit appeler le
constructeur de copie de tous ses attributs - class Voiture
-
- private Moteur moteur
- private int nbPortes
- private double cylindree
- public Voiture(Voiture v)
-
- moteur new Moteur(v.moteur)
- nbPortes v.nbPortes
- cylindree v.cylindree
-
26Construction correcte résultat
Voiture objet créé avec new
Moteur objet créé avec new
mavoiture
voiture_2
Voiture objet créé avec new
Moteur objet créé avec new
mavoiture new Voiture() voiture2 new
Voiture(mavoiture)
27Usage de clone()
- class Voiture implements Cloneable
-
- private Moteur moteur
- private int nbPortes
- private double cylindree
- public Object clone()
-
- Voiture v new Voiture()
- v.moteur (Moteur) moteur.clone()
- v.nbPortes nbPortes
- v.cylindree cylindree
- return v
-
28Copie profonde
- On voit que dupliquer un objet complexe suppose
de dupliquer tous ses composants - Cela entraîne des appels en cascade de copies
jusquaux types de base - Les constructeurs de copies ne sont pas fournis
pour les classes du JDK - Pour la copie profonde, préférer clone(), fournie
pour les classes du JDK - Attention, les constructeurs de copie des
collections ne dupliquent pas les objets contenus
29Passage de paramètres
30Cas du passage d'un objet
- Quand on passe un objet en paramètres, cest une
référence sur cet objet qui est passée et copiée - On passe par valeur des types de base et des
référence
23.3
Voiture
main()
methode(v)
v1
reference
reference
v
31Passage dobjets en paramètres
- Quand on passe un objet en paramètres, cet objet
peut être modifié à l'intérieur de la méthode - Donc si lobjet est modifié dans la méthode, les
modifications seront visibles de lextérieur - Ce comportement est contraire au cas où on passe
des types de base en paramètre les
modifications ne sont pas vues de lextérieur - Solution faire une copie des paramètres avant
l'appel
32Passage d'un objet sans modification interne
23.3
Voiture
23.3
Voiture
main()
v1
reference
methode(v)
X
reference
reference
main() methode(new Voiture(v1))
v
33Destruction des objets
- L'appel d'un constructeur réalise une allocation
dynamique de mémoire - En C, il faut penser à libérer la mémoire
allouée lorsqu'on na plus besoin de l'objet - 30 à 40 du temps passé à trouver les bugs de
gestion de la mémoire - En Java, c'est inutile il y a un
ramasse-miettes (Garbage Collector) qui libère la
mémoire quand un objet ne sert plus
34Attributs et méthodes de classe (ou statiques
)
35Attributs statiques
- On dit aussi ltlt attribut de classe gtgt (par
opposition à ltlt attribut dinstance gtgt) - La portée d'un attribut statique est la classe et
non l'objet - Une seule instance d'un attribut statique, au
niveau de la classe - Tous les objets partagent la même valeur pour cet
attribut - class Mot
-
- private long id
- private static long next 0
- Mot()
-
- id next
-
36Méthodes statiques
- On dit aussi méthode de classe
- On peut appeler ces méthodes sans créer l'objet
- MaClasse.maMethode()
- Une méthode statique ne peut utiliser que des
attributs statiques - Cas particulier la méthode main()
- public static void main(String args)
-
- Voiture mavoiture new Voiture(2.80)
- mavoiture.demarrer()
- mavoiture.conduire()
- mavoiture.stopper()
-
37Exemple la classe Math
- Ensemble de méthodes de classe (statiques)
- Math.exp(double)
- Math.random()
- Math.sin(), Math.cos()
38Conventions de notation
- class MaClasse majuscule pour les classes et
pour les premières lettres de chaque mot - int maVariable minuscule pour les variables,
attributs et méthodes, mais majuscule pour les
premières lettres de chaque mot - accesseurs get et set NomAttribut (params)
- Une seule classe par fichier, le fichier porte le
nom de la classe
39Divers
40La classe String
- Initialisation
- Directe, sans constructeur
- String maChaine1 bonjour
- Avec constructeur
- String maChaine2 new String( Monsieur )
- Concaténation avec lopérateur
- String maChaine3 maChaine1 maChaine2
- gt maChaine3 ltlt bonjour Monsieur
41La classe String (2)
- Quelques méthodes
- public char charAt(int i)
- ième caractère
- public int length()
- Longueur de la chaîne
- public String substring(int indice, int longueur)
- Sous-chaîne
42La classe System
- Permet daccéder à différentes fonctionnalités du
système, en particulier les entrées-sorties - Les variables in, out et err permettent daccéder
à lentrée standard, la sortie standard, et la
sortie standard derreur - public static currentTimeMillis() renvoie le nb
de millisecondes depuis 01/01/1970 - public static void exit(int status) permet de
quitter le programme avec un code de sortie
(status)
43Quelques codes utiles
44Une classe Chrono
- package Util
- import java.util.
- public class Chrono
-
- protected Date debut
- protected Date fin
- public Chrono()
-
- debut new Date() //démarrage du chrono
-
- public void stop()
-
- fin new Date()
- printTime(fin.getTime()-debut.getTime())
-
-
45Classe Chrono (suite)
- public void printTime (long duree)
- if (dureelt1000) System.out.println(duree ms
) - else
- int sec duree/1000
- int resteMs duree-1000sec
- if (seclt60) System.out.println(sec s
resteMs ms ) - else
- int min sec/60
- int resteSec sec-60min
- if (minlt60) System.out.println(min mn
resteSec s resteMs ms ) - //
-
-
-
46Classe Chrono (utilisation)
- public class TestChrono
-
-
- public static void main(String toto)
-
- int n Integer.parseInt(toto0)
- Chrono monChrono new Chrono() //demarrage du
chrono - for (int i0iltni)
-
- double perteDeTemps Math.exp(Math.sqrt((doubl
e)i)) -
- monChrono.stop() //affichage du temps
-
-
47Une classe FileWriter
- package Util
- import java.util. //utilise File, PrintWriter,
FileOutputStream - public class FileWriter
-
- protected FileOutputStream myFileStream null
- protected PrintWriter myWriter null
- protected String myFileName NomFichier
- // les accesseurs et modifieurs ne sont pas
présentés - public FileWriter()
- public FileWriter(String fileName)
- myFileName filename
- open()
-
- public FileWriter(String dir, String fileName)
- boolean success (new File(dir)).mkdirs()
- if (!success) System.out.println( Writer
mkdir failure ) - myFileName filename
- open()
48Classe FileWriter (suite)
- public class FileWriter
- public void open()
- close()
- try
- myFileStream new FileOutputStream(getFileNam
e()) - myWriter new PrintWriter(getFileStream())
-
- catch(Exception e)
- e.printStackTrace() System.exit(-1)
-
-
- public void close()
-
- try
- if (getFileStream()!null) getFileStream.close(
) -
- catch(Exception e)
- e.printStackTrace() System.exit(-1)
-
49Classe FileWriter (suite)
public class FileWriter public void
print(String sortie) getWriter().print(sortie)
getWriter().flush() public void
println(String sortie) getWriter().println(sor
tie) getWriter().flush() public void
flush() getWriter().flush()
public class TestFileWriter public static void
main(String argv) FileWriter fw new
FileWriter ( /home/chezmoi/ici/ , nomfich
) fw.println(contenu ) fw.close()
- Lencapsulation permet de cacher tous les appels
complexes pour se servir dun FileWriter de façon
très simple
50Une classe LireURL
- import java.net.
- public class LireURL
-
- public static void main(String argv)
- URL url null
- String nom http//www.google.com
- if (argv.lengthlt1)
- nom argv0
-
- try
- url new URL(nom)
-
- catch(MalformedURLException e)
-
51Classe LireURL (suite)
- public static void main(String argv)
-
- try
- URLConnection connexion url.openConnection()
- LineNumberReader lecture new
LineNumberReader(new InputStreamReader(connexion
.getInputStream())) - int length connexion.getContentLength()
- for (int i0iltlengthi)
- ligne lecture.readline()
- if (lignenull) System.exit(-1)
- System.out.println(ligne)
-
-
- catch(IOException e)