2
votes

Que se passe-t-il lorsqu'un objet est uniquement défini?

Je me demandais ce qui se passe au niveau de la mémoire lorsqu'un objet est défini, mais pas initialisé.

Par exemple:

public class MainClass {
 public static void main (String[] args){
  Object foo;
 }
}

Est foo em > pointant vers un espace mémoire? Ce comportement change-t-il entre les différents langages de programmation?

Merci d'avance.

Edit: Je sais que l'objet pointera vers null lorsqu'il est utilisé, mais je le suis intéressé de savoir ce qui se passe juste après que l'objet a été défini, et pas encore instancié. Y a-t-il une référence à la mémoire dans ce cas?


4 commentaires

Il y a juste une variable ici. Pas d'objet.


En java, vous avez simplement une référence à "rien". Pas d'objet. Cependant, en C ++ par exemple, vous obtenez un objet réel dans ce cas. Ceci afin de répondre à la deuxième partie de votre question.


Les variables à l'intérieur d'une méthode sans aucun modificateur sont créées sur la pile.


Pour résumer un peu: En Java, si Object foo; est utilisé comme membre, il sera initialisé à null . S'il est utilisé dans une méthode, vous devez initialiser foo par vous-même, dans mes tests, il était possible d'exécuter le code autrement. C ++ gère les choses un peu différemment. Ici, Object foo; provoquera l'appel du constructeur par défaut, peu importe où il est placé.


3 Réponses :


1
votes

En java, foo pointera vers "null" lorsqu'il définira en classe, et foo ne pointera vers rien là où il définit dans function.


0 commentaires

1
votes

En Java, vous pouvez considérer les variables d'objet comme des pointeurs. Par défaut, ils ne pointent vers rien, seul le pointeur lui-même est alloué (par exemple 8 octets sur la pile).

Vous pouvez le faire pointer vers une instance réelle d'un objet en allouant cet objet et en l'assignant à la variable: >

Object foo; // points to nothing (and may not be used)

foo.toString(); // compile error: The local variable obj may not have been initialized

foo = new Object(); // points to an instance of a new Object

foo = null; // again points to nothing, but is now initialized

foo.toString(); // will compile, but throw NullPointerException at run time

Ceci est fondamentalement différent de C ou C ++, où Object foo; serait en fait un objet local alloué sur la pile. Java n'alloue jamais d'objets sur la pile, uniquement des types primitifs ou des pointeurs.


3 commentaires

Je pense que c'est un petit malentendu. Si seulement déclaré, non initialisé, une vérification comme foo == null ne compilera pas non plus (variable non initialisée), du moins dans mes tests. Dans votre deuxième phrase ("Par défaut, ils ne pointent vers rien ( null ), [...]") on pourrait comprendre, que foo == null renvoie < code> vrai .


"pointe vers une référence " peut être plus précis. De plus, rien n'est égal à null . Comme une variable unifiée ne sera pas affectée à null


La valeur réelle qu'une variable non initialisée contient réellement n'est pas spécifiée. Mais une fois qu'un slot est alloué dans le bytecode, la JVM l'initialise toujours à 0. Cela n'a pas d'importance car le code qui utilise une telle variable ne peut pas être compilé.



2
votes

Je me demandais ce qui se passe au niveau de la mémoire lorsqu'un objet est défini, mais pas initialisé.

Supposons que nous parlons ici de Java.

Je dois d'abord corriger votre description incorrecte. (Pour des raisons qui deviendront apparentes ...)

Il ne s'agit pas de définir un objet . Il s'agit plutôt de déclarer une variable . L'identifiant foo désigne une variable . Comme le type de la variable est (dans ce cas) Object qui est un type de référence, la variable peut contenir soit une référence à un objet Java soit null < / code>.

Est-ce que foo pointe vers un espace mémoire?

La réponse est un peu compliquée.

  • Si la variable est initialisée, elle pointera vers un objet ou elle contiendra null.

  • Si la variable n'est PAS initialisée, cela dépend du type de variable dont nous parlons:

    • Pour un champ d'une classe (statique ou instance), une variable qui n'est pas explicitement initialisée est initialisée par défaut à null .

      < / li>
    • Pour une variable qui est un paramètre ou une variable catch, la sémantique du langage Java garantit que la variable est toujours initialisée ... c'est donc sans objet.

    • Pour une variable locale, le JLS ne dit pas ce qu'elle contient avant qu'une valeur ne lui soit affectée. Vous pourriez dire que la valeur est indéterminée. Cependant le JLS (et au moment de l'exécution, le vérificateur de fichiers de classe de la JVM) garantit qu'un programme ne peut pas utiliser une variable locale qui est dans un état indéterminé. (C'est une erreur de compilation dans le code Java de lire une variable qui n'a pas été définitivement assignée .) Donc, ce que la variable contient réellement ne fait vraiment aucune différence.

Notez qu'en Java pur, il n'est jamais possible pour une variable de contenir une valeur qu'elle n'a pas été définie par affectation ou initialisation. Ainsi, une variable ne peut jamais faire référence à une adresse mémoire aléatoire. (Si vous utilisez du code natif, il est possible que le code corrompe une variable pour contenir quoi que ce soit. Mais ne le faites pas délibérément car cela risque de faire planter la JVM.)

Ce comportement change-t-il entre les différents langages de programmation?

Euh ... oui. Par exemple, en C et C ++, un programme peut utiliser la valeur d'une variable de pointeur qui n'a pas été initialisée. Le comportement qui en découle est non spécifié .


2 commentaires

Comme vous l'avez déjà dit, en Java, les objets ressemblent plus à des références. Comme indiqué également, les objets Java sont mieux décrits avec des pointeurs en C ++. Mais pour ajouter à l'exhaustivité, vous n'avez pas besoin de créer un pointeur en C ++. En indiquant uniquement Object foo; , C ++ appellera le constructeur par défaut.


@ TobiasBrösamle - Je n'ai pas essayé d'expliquer toutes les différences entre les déclarations C ou C ++ et Java. Ce serait une question différente (et trop large!).