Je sais juste que les non-primitives (les objets) vont sur le tas, et les méthodes vont sur la pile, mais qu'en est-il des variables primitives?
- mise à jour
Sur la base des réponses, je pourrais dire que le tas peut avoir une nouvelle pile et un tas pour un objet donné? Étant donné que l'objet aura des variables primitives et de référence ..?
Les primitives définies localement seraient sur la pile. Cependant, si une primitive était définie comme faisant partie d'une instance d'un objet, cette primitive serait sur le tas.
public class Test {
private static class HeapClass {
public int y; // When an instance of HeapClass is allocated, this will be on the heap.
}
public static void main(String[] args) {
int x=1; // This is on the stack.
}
}
En ce qui concerne la mise à jour:
Les objets n'ont pas leur propre pile. Dans mon exemple, int y
Ferait en fait partie de chaque instance de HeapClass
. Chaque fois qu'une instance de HeapClass est allouée (par exemple new Test.HeapClass()
), toutes les variables membres de HeapClass sont ajoutées au tas. Ainsi, puisque des instances de HeapClass
sont allouées sur le tas, int y
Serait sur le tas dans le cadre d'une instance de HeapClass
.
Cependant, toutes les variables primitives déclarées dans le corps d'une méthode seraient sur la pile .
Comme vous pouvez le voir dans l'exemple ci-dessus, int x
Est sur la pile car il est déclaré dans un corps de méthode - pas en tant que membre d'une classe.
on trouve des primitives aux deux endroits.
class Foo
{
public int x;
public static void Main()
{
int y = 3; // y is on the stack
Foo f = new Foo(); // f.x is probably on the heap
}
}
sauf que vous ne devriez pas vraiment vous en soucier, sauf si vous créez une machine virtuelle Java. Un optimiseur vraiment intelligent pourrait décider que puisque le Foo que f pointe vers n'échappe jamais à Main et n'est jamais passé à une autre fonction, il est sûr de l'allouer sur la pile.
En ce qui concerne la mise à jour:
La pile et le tas ne se distinguent pas par ce qui y est stocké, mais plutôt par les opérations qui leur sont fournies. La pile vous permet d'allouer un morceau de mémoire d'une manière LIFO, vous ne pouvez pas désallouer un morceau tant que tous les morceaux plus jeunes que lui n'ont pas été désalloués. Cela s'aligne facilement avec la façon dont un appel la pile est utilisée. Vous pouvez mettre n'importe quoi sur la pile tant qu'il est acceptable que cette chose disparaisse lorsque votre fonction revient. C'est une optimisation, car il est très rapide d'allouer et de désallouer à partir d'une pile car il ne supporte que d'être utilisé de cette manière. On pourrait stocker toutes les variables locales pour une fonction sur le tas dans une implémentation si on le voulait. Le tas est plus flexible, et par conséquent plus cher à utiliser. Il ne serait pas exact de dire qu'un objet a une pile et un tas, comme je l'ai dit, ce qui distingue la pile du tas n'est pas ce qui s'y trouve, mais les opérations disponibles.
Les valeurs primitives sont allouées sur la pile à moins que ce ne soient des champs d'un objet, auquel cas elles vont sur le tas. La pile est utilisée pour l'évaluation et l'exécution, donc non, cela n'a pas de sens de dire que les objets avec des champs primitifs ont une pile - elle est toujours considérée comme faisant partie du tas. Même les objets Stack
sont alloués sur le tas.