Java avancé

publicité
Java avancé
Modèle d'exécution
Modèle d'exécution en mémoire
●
Différents types de mémoire d'un programme
–
Données read-only :
●
–
données r/w :
●
–
variables globales.
Pile :
●
●
–
code du programme, constantes
une par thread
exécute opération courante
Tas :
●
objets alloués (par malloc ou new)
Allocation en Java
●
●
●
En Java, les variables locales (variables de types primitifs
et références) sont allouées sur la pile (ou dans les
registres) et les objets dans le tas.
Le développeur ne contrôle pas la zone d'allocation ni
quand sera effectuée la désallocation.
En C++, il est possible d'allouer des objets sur la pile, pas
en Java.
Sur la pile
●
●
La pile, l'ensemble des valeurs courantes d'une
exécution :
Sur la pile :
–
Un type primitif est manipulé par sa valeur
(sur 32bits ou 64bits)
–
Un type objet est manipulé par sa référence
Pile
int i;
Point p;
i=3;
p=new Point();
i
3
p
Variables locales
Tas
Point
La référence null
●
Java possède une référence spéciale null, qui
correspond à aucune référence.
Point p;
p=null;
Holder h;
h=null;
System.out.println(p.x);
// lève une exception NullPointerException
●
●
null est une référence de n'importe
quel type
null instanceof Truc renvoie toujours faux
Référence != Pointeur
●
●
Une référence (Java) est une adresse d'un objet en
mémoire
Un pointeur (C) est une référence plus une arithmétique
associée
Point p;
// Java
p=new Point();
p++; // illegal
Point *p;
p=new Point();
p++; // legal
// C
●
Une référence ne permet pas de parcourir la mémoire,
●
elle pointe toujours soit sur un objet, soit est null.
Variable et type
●
Simulons l'exécution du code :
int i=3;
int j=i;
j=4;
Truck t=new Truck();
t.wheel=3;
Truck u=t;
u.wheel=4;
●
Variables locales
i
3
j 43
champs
wheel 4 3
Variables locales
t
u
u contient la même référence que t.
Passage de paramètres
●
Les paramètres sont passés par copie
private static void f(int i,String s,Truck t) {
i=4;
s="toto";
t.wheel=3;
Variables locales
t=new Truck();
i 4 2
}
ss
t
●
Les objets sont manipulés par des
références copiées
public static void main(String[] args) {
String arg="zut";
int value=2;
Truck truck=new Truck();
f(value,arg,truck);
System.out.printf("%d %s %h %d\n",
value,arg,truck,truck.wheel);
}
toto
wheel
wheel 3 0
Variables locales
arg
value
truck
0
2
zut
Objets mutables et non mutables
●
●
Une objet est mutable s'il est possible de modifier son
état après sa création
Sinon il est non-mutable
–
champs final ou privés sans setter pour les types primitifs
–
méthode ne permettant que la consultation
–
objets levant une exception quand on essaye de les modifier
(e.g. Collection.unmodifiable*)
Objets mutables et non mutables
public class Point {
private final int x,y;
public int getX() {return x;}
public int getY() {return y;}
}
public class UnmutableList {
private final ArrayList<String> list;
public String get(int index) {
return list.get(index);
}
public class UnmutableList<T> implements List<T> {
public boolean add(T member) {
throw new UnsupportedOperationException();
}
}
Objets mutables et non mutables
●
Pour effectuer des opérations sur les objets non
mutable, il faut créer un nouvel objet:
String name = "JULIETTE";
String lowName = name.toLowerCase();
String entry = name.replace('T','N');
System.out.println(name) // JULIETTE
System.out.println(lowName) // juliette
System.out.println(entry) // JULIENNE
●
L'objet « chaîne de caractères mutable » est l'objet
StringBuilder
Protection des données
●
●
En fournissant une référence en appelant une méthode
ou comme valeur de retour, ou acceptant une référence
en étant appelé, on prend le risque que l'objet appelant
modifie la valeur de l'objet pendant ou après l'appel de
la méthode
Pour palier cela
–
passer une copie/effectuer une copie de l'argument (lourd,
surtout si l'objet extérieur fait de même)
–
passer/accepter un objet non mutable (lourd, surtout si les
données changent souvent)
Tests d'égalité
●
Les opérateurs de comparaison == et != testent les
valeurs des variables :
–
Pour les types primitifs, on test leurs valeurs
–
Pour les types objets, on test les valeurs des références
Truck
a=new
Truck
b=a;
Truck
a;
Truck();
b;
c=new Truck();
a==b; // true
b==c; // false
a==c; // false
Variables locales
a
b
c
wheel 4
wheel 4
Tests d'égalité
●
●
●
Pour comparer sémantiquement deux objets, la classe
correspondante doit redéfinir la méthode
Object.equals(Object)
La méthode equals de Object teste les références
La plupart des classes de données de l'API redéfinissent
la méthode equals
Point a;
a=new Point(2,2);
Point b=new Point(2,2);
a.equals(b); // true
a==b; // false
Tests d'égalité
●
●
●
Tout objet redéfinissant equals doit redéfinir
hashcode si l'objet doit être utilisé dans les collections
basées sur un hachage (donc tout le temps)
equals doit être symétrique, transitive, réflexive, et
ne doit pas lever d'exception.
Éviter de surcharger equals
class Point {
private final int x,y;
@Override public boolean equals(Object o) {
if (! (o instanceof Point))
return false;
Point p = (Point)o;
return x==p.x && y==p.y // accès aux champs privés
// d'une autre instance
}
}
Tests d'égalité
●
equals et hashcode doivent vérifier
–
●
●
●
x.equals(y) implique x.hashcode()==y.hashcode()
les valeurs de hashcode doivent de préférence être
différentes pour les valeurs des objets utilisés par le
programme
hashcode ne doit pas changer si l'objet ne change pas
(et il ne doit pas changer pendant qu'il est dans une
collection)
hashcode doit être rapide à calculer (éventuellement
précalculée pour les objets non mutables).
hashcode
class Point {
private final int x,y;
@Override public boolean equals(Object o) {
if (! (o instanceof Point))
return false;
Point p = (Point)o;
return x==p.x && y==p.y
}
/* mauvais hashcode :
@Override public int hashcode() {
return x-y;
} */
}
@Override public int hashcode() {
return x^Integer.reverseBytes(y);
}
Désallocation en Java
●
●
●
●
Les objets qui ne sont plus référencés vont être collectés
(plus tard) par le GC pour que leur emplacement
mémoire soit réutilisé.
Façons d'avoir un objet non référencé :
–
Si on assigne une nouvelle référence à une variable
(l'ancienne référence “meurt”)
–
Si l'on sort d'un bloc, les variables locales “meurent”.
Il faut qu'il n'y ait plus aucune référence sur un objet
pour qu'il puisse être réclamé
Mécanisme de références faibles.
Désallocation en Java
●
Un objet sera réclamé par le GC si aucune référence sur
lui ne persiste.
{
Point p;
p=new Point();
{
Point p;
p=new Point();
}
p=null;
}
Pile
p
●
@Point
Point p2;
p2=p;
p=null;
Pile
p
p2
@Point
Penser à mettre les références des gros objets à null
quand ils ne sont plus utilisés (pas la peine de mettre
leurs champs à null)
Téléchargement