Nous avons déjà utilisé le concept d'« objet », mais nous n'avons pas discuté de la manière spécifique dont les objets sont stockés en mémoire. Cette discussion mènera au concept important de « référence d’objet ».
référence d'objet
Nous continuons à utiliser la classe Human définie précédemment et avons une classe Test :
Copiez le code comme suit :
Test de classe publique
{
public static void main (String[] arguments)
{
Humain aPerson = nouvel Humain (160);
}
}
classeHumain
{
/**
* constructeur
*/
humain public (int h)
{
ceci.hauteur = h;
}
/**
*accesseur
*/
public int getHeight()
{
renvoie this.height;
}
/**
* mutateur
*/
public void growHeight (int h)
{
ceci.hauteur = ceci.hauteur + h;
}
hauteur int privée ;
}
Les classes peuvent être appelées en externe pour créer des objets, comme ci-dessus dans la classe Test :
Copiez le code comme suit :
Humain aPerson = nouvel Humain (160);
Un objet aPerson de classe Human est créé.
Ce qui précède est une déclaration très simple, mais nous devons entrer dans de nombreux détails :
1. Regardez d’abord le côté droit du signe égal. new ouvre de l'espace pour les objets en mémoire. Plus précisément, new ouvre de l'espace pour les objets sur le tas de mémoire. Dans cet espace, les données et méthodes de l’objet sont stockées.
2. Regardez le côté gauche du signe égal. aPerson fait référence à un objet humain, appelé référence d'objet. En fait, aPerson n'est pas l'objet lui-même, mais est similaire à un pointeur vers l'objet. aPerson existe dans la pile en mémoire.
3. Lorsque nous utilisons le signe égal pour attribuer une valeur, l'adresse de l'objet créé dans le tas par new à droite est affectée à la référence de l'objet.
La mémoire fait ici référence à l'espace mémoire du processus Java virtualisé par la JVM (Java Virtual Machine). Pour les concepts de tas et de pile en mémoire, veuillez vous référer à Linux From Program to Process.
La pile peut être lue plus rapidement que le tas, mais les données stockées sur la pile sont limitées par la plage valide. En langage C, lorsqu'un appel de fonction se termine, le frame de pile correspondant est supprimé, et les paramètres et variables automatiques stockés sur le frame de pile disparaissent. La pile Java est également soumise à la même restriction. Lorsqu'un appel de méthode se termine, les données stockées sur la pile par la méthode seront effacées. En Java, tous les objets (ordinaires) sont stockés sur le tas. Par conséquent, la pleine signification du mot-clé new est de créer un objet sur le tas.
Les objets de types primitifs, tels que int et double, sont stockés sur la pile. Lorsque nous déclarons un type de base, il n’est pas nécessaire d’en ajouter un nouveau. Une fois déclaré, Java stocke les types primitifs de données directement sur la pile. Par conséquent, le nom de variable d’un type de base représente les données elles-mêmes et non une référence.
La relation entre les références et les objets est comme un cerf-volant et une personne. Quand on regarde le ciel (écrit dans le programme), ce qu'on voit c'est un cerf-volant (référence), mais ce qui correspond au cerf-volant c'est une personne (objet) :
Séparation des références et des objets ; les références pointent vers des objets.
Bien que les références et les objets soient séparés, tous nos accès aux objets doivent passer par la « porte » des références, comme l'accès aux méthodes objet via reference.method(). En Java, nous ne pouvons pas ignorer les références et toucher directement les objets. Pour un autre exemple, si les données membres de l'objet a sont un objet ordinaire b, les données membres de a enregistrent une référence à l'objet b (s'il s'agit d'une variable de type de base, alors les données membres de a enregistrent la variable de type de base elle-même) .
En Java, les références jouent le rôle de pointeurs, mais on ne peut pas modifier directement la valeur du pointeur, comme par exemple ajouter 1 à la valeur du pointeur comme en langage C. Nous ne pouvons effectuer des opérations sur des objets que via des références. Cette conception évite de nombreuses erreurs que les pointeurs peuvent provoquer.
mission de référence
Lorsque nous attribuons une référence à une autre référence, nous copions en fait l'adresse de l'objet. Les deux références pointeront vers le même objet. Par exemple, dummyPerson=aPerson donnera :
Un objet peut avoir plusieurs références (une personne peut faire voler plusieurs cerfs-volants). Lorsqu'un programme modifie un objet via une référence, la modification est visible via d'autres références. Nous pouvons utiliser la classe Test suivante pour tester l'effet réel :
Copiez le code comme suit :
Test de classe publique
{
public static void main (String[] arguments)
{
Humain aPerson = nouvel Humain (160);
Personne factice humaine = aPerson ;
System.out.println(dummyPerson.getHeight());
aPerson.growHeight(20);
System.out.println(dummyPerson.getHeight());
}
}
Nos modifications apportées à aPerson affecteront dummyPerson. Ces deux références pointent en réalité vers le même objet.
Par conséquent, l’attribution d’une référence à une autre référence ne copie pas l’objet lui-même. Il faut trouver d'autres mécanismes pour copier des objets.
Collecte des déchets
À la fin de l’appel de méthode, les variables de référence et de type primitif sont effacées. Puisque l'objet vit sur le tas, la mémoire occupée par l'objet ne sera pas effacée à la fin de l'appel de méthode. L'espace de processus peut rapidement se remplir d'objets en cours de création. Java dispose d'un mécanisme de récupération de place intégré pour effacer les objets qui ne sont plus utilisés pour récupérer de l'espace mémoire.
Le principe de base du garbage collection est que lorsqu'il y a une référence pointant vers un objet, l'objet ne sera pas recyclé ; lorsqu'il n'y a aucune référence pointant vers un objet, l'objet est effacé ; L'espace qu'il occupe est récupéré.
La figure ci-dessus suppose l'état de la mémoire dans la JVM à un moment donné. L'objet humain a trois références : aPerson et dummyPerson de la pile, et le président, une donnée membre d'un autre objet. L'Objet Club n'a aucune référence. Si le garbage collection est démarré à ce moment-là, l'objet Club sera vidé et la référence de l'objet humain (président) de l'objet Club sera également supprimée.
Le garbage collection est un mécanisme important en Java, qui affecte directement l'efficacité opérationnelle de Java. J'entrerai dans les détails plus tard.
Passage de paramètres
Lorsque l'on sépare les concepts de références et d'objets, le mécanisme de passage des paramètres des méthodes Java est en fait très clair : le passage des paramètres Java se fait par valeur. Autrement dit, lorsque nous transmettons un paramètre, la méthode obtiendra une copie du paramètre.
En fait, l'un des paramètres que nous passons est une variable de type basique et l'autre est une référence à l'objet.
Le passage par valeur pour les variables de type primitif signifie que la variable elle-même est copiée et transmise à la méthode Java. Les modifications de variables par les méthodes Java n'affecteront pas les variables d'origine.
Le passage par valeur signifie que l'adresse de l'objet est copiée et transmise à la méthode Java. L'accès à la méthode Java basé sur cette référence affectera l'objet.
Il y a une autre situation qui mérite d'être mentionnée ici : nous utilisons new à l'intérieur de la méthode pour créer un objet et renvoyer une référence à l'objet. Si le retour est reçu par une référence, puisque la référence de l'objet n'est pas 0, l'objet existe toujours et ne sera pas récupéré.
Résumer
nouveau
référence, objet
Conditions de collecte des déchets
Paramètres : transmis par valeur