Disons que j'ai trois classes:
class A {
A() {
// super();
System.out.println("class A");
}
}
class B extends A {
B() {
// super();
System.out.println("class B");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //Parent constructor will get called
}
}
Lorsque je crée une instance de classe C, elle appelle le constructeur de super classe. Alors, y a-t-il plus d'un objet en cours de création? Si un seul objet est créé, comment super () ressemble-t-il au constructeur d'une autre classe? La méthode super () crée-t-elle en interne un objet? Ce que je sais, c'est que le constructeur est aussi une méthode (je peux me tromper).
Mes questions sont:
Excellente question. Ce que vous recherchez, c'est comment Java initialise les objets - et il y a un certain nombre d'étapes impliquées.
je sais que son constructeur est aussi une méthode (peut-être que je me trompe).
Presque raison. Le constructeur est une méthode spéciale. Si vous décompilez un fichier de classe, vous verrez que les constructeurs sont renommés en <init>
. <init>
est traité différemment des autres méthodes et, par exemple, ne peut pas être appelé explicitement, sauf en utilisant le mot clé new
ou super
. Ceci est tellement fondamental qu'il est implémenté dans la machine virtuelle elle-même plutôt que d'être défini dans le langage Java.
Combien de nombre d'objets est créé dans ce cas.
Un objet est créé - une instance de C
.
C
est en plus et simultanément une instance de B
et une instance de A
et aussi Object
.
Si un objet est créé, comment
super()
appelle en interne la classe parent Constructor. Comment Super est capable d'appeler le constructeur de la classe parent.
C’est là que nous entrons dans l’initialisation - l’initialisation est la façon dont la machine virtuelle Java crée une nouvelle instance d’un objet et définit toutes les valeurs de membre - celles de la classe spécifique et celles des superclasses. Il y a plusieurs étapes impliquées:
A
, B
et C
.NOTEceci explique un aspect de votre question: comment les constructeurs de la classe de base et de ses sous-classes peuvent-ils se mettre à jour ou se référer au même objet - tous les membres de l’instance de toutes les classes sont stockés un après l’autre dans le même bloc de mémoire. int
et float
seront définis sur 0 et 0.0f.Exécutez ou calculez les initialiseurs de membres, par exemple:
private int a = 10;
private int b = a * 5;
private String c = Singleton.getInstance().getValue();
Remarque (1) cette initialisation de membre se produit strictement dans l'ordre dans lequel les membres sont déclarés dans la classe. Cela signifie que les références aux membres plus tard dans la déclaration sont cassées:
private int a = b * 5; // Forward reference; won't compile
private int b = 10;
Remarque (2) qu'il existe une fonctionnalité sous-utilisée en Java pour exécuter du code arbitraire afin d'initialiser les valeurs avant le constructeur est exécuté. Ces blocs de code sont exécutés à ce moment encore strictement dans l’ordre de déclaration:
private int a;
private int b = 1;
{
// Initization occurs after b but before c.
// c cannot be referenced here at all
int i = SomeClass.getSomeStatic();
a = i * 2;
}
private int c = 99;
Exécutez le constructeur de C
. Les constructeurs doivent soit appeler directement un constructeur de la super-classe, sinon le compilateur ajoutera automatiquement super()
en tant que première ligne du constructeur. Cela signifie que les constructeurs sont strictement exécutés dans l'ordre:
Object
A
B
C
L'objet est maintenant initialisé et prêt à être utilisé. Vous pouvez faire des choses dangereuses si vous initialisez une valeur en utilisant des méthodes d'instance:
public class Wrong {
int a = getB(); // Don't do this!
int b = 10;
public int getB() {
return b;
}
}
Ici, a
est initialisé à 0
. En effet, au point où getB()
est appelé, Java a effacé la valeur par défaut de b
(0
), mais ne l'a pas encore définie sur 10
dans la deuxième phase d'initialisation.
En résumé - il n'y a qu'un seul objet et il est créé et initialisé en nombre par étapes. Au cours de ces étapes, l’objet n’est, par définition, pas complètement défini.
Dans Code, un seul objet sera créé et le super appel du constructeur de la classe parent.
Prouver la création d'objet:
package one;
public class A {
public static A super_var;
public A() {
super_var = this;
System.out.println("Constrcutor of A invoked");
}
}
package two;
public class B extends A {
public static A sub_var;
public B() {
sub_var = this;
System.out.println("Constructor of B invoked");
}
public void confirm() {
if (sub_var == A.super_var)
System.out.println("There is only one object is created");
else
System.out.println("There are more than one object created");
}
public static void main(String Args[]) {
B x = new B();
x.confirm();
}
}
Cela prouvera qu'il n'y aura qu'un seul objet créé.
Et à propos de Super()
. Ce que je sais qu’il appelle le constructeur de la classe Parent. et chaque constructeur a Super()
comme première déclaration, comme vous le mentionnez dans votre code. pour que vous sachiez
Je ne sais pas comment il appelle en interne un constructeur de super classe.
J'espère que cela vous fera comprendre qu'il n'y a que l'instace que vous créez dans le programme
Il y aura un et un seul objet sera créé et c'est à dire. Un objet.
Vous pouvez imaginer que lorsque la classe A étend B, toutes les méthodes et variables sont copiées dans la classe A.
Invoquer un constructeur ne signifie pas que vous créez des objets. L'objet est déjà créé lors de l'appel du constructeur. Les objets sont d'abord créés par la machine virtuelle (la mémoire est allouée sur le tas, puis le constructeur est appelé).
Constructeur sont destinés à initialiser les membres des objets.
Vos cours seront convertis en interne en quelque chose comme ça
class A
{
A(){
super();
System.out.println("class A");
}
}
class B extends A{
B(){
super();
System.out.println("class B");
}
}
public class C extends B
{
public static void main(String args[])
{
C c = new C(); //Parent constructor will get call
}
}
Combien de nombre d'objets est créé dans ce cas.
Un seul, instance de C
, appelle super()
uniquement appelle le constructeur de la classe parent et ne crée pas d'objet
Si un objet est créé, comment Super () appelle Parent .__ en interne. classe constructeur. Comment Super est capable d'appeler la classe parente constructeur.
Lorsque vous créez l'instance de C
. Le constructeur de C
est appelé, ce qui appelle d'abord le constructeur de B
, qui à son tour appelle le constructeur de A
.
Dans votre cas, un objet est créé
en effectuant ce qui suit, ce super () sera fourni implicitement par le compilateur
class A {
A() {
System.out.println("class A");
}
}
class B extends A {
B() {
System.out.println("class B");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //
}
}
C'est comme appeler un super () dans vos méthodes
B() {
super();
System.out.println("class B");
}
Le mot clé super peut également être utilisé lorsqu'une méthode est substituée dans la classe actuelle, mais que vous souhaitez invoquer la méthode super class.
super () will fera référence à tous les constructeurs à une classe. (Pour faciliter la compréhension: toutes les fonctions membres appartiennent à la même classe.) Il n’appelle que toutes les méthodes constructeurs.
Donc, son travail consiste à appeler uniquement le constructeur, donc super () ne créera pas d'objet. C'est juste en se référant aux fonctions membres.
Étapes de la création d'un objet lorsque vous appelez un constructeur pour créer un objet:
L'allocation de mémoire en utilisant init est faite. Cet init effectue un appel système pour allouer de la mémoire à la création d'un objet.
Ensuite, votre constructeur est appelé pour initialiser les champs de l'objet.
Ensuite, il appelle le constructeur de la super classe (s'il existe une super classe) et les répétitions des étapes 1 à 3.
Ce que vous voyez lorsque vous décompilez un fichier de classe en utilisant javap indique les différents appels à effectuer. init effectue un appel système pour initialiser l'allocation de mémoire, mais le champ de l'objet est initialisé lors de l'exécution du code du constructeur.
Je ne suis pas sûr de savoir comment fonctionne le polymorphisme/neutralisation au moment de la GC.
Toutefois, il convient de tenter de remplacer la méthode finalize
dans toutes vos classes et de vérifier quand la machine virtuelle Java quitte la méthode principale.
C
est créé, il doit appeler finalize
pour 'C'.A
, B
, C
est créé, il doit appeler finalize
pour A
, B
, C
.Je pense que c'est la vérification la plus simple que vous pouvez appliquer.
class A {
A() {
//Super();
System.out.println("class A");
}
public void finalize(){
System.out.println("Class A object destroyed");
}
}
class B extends A {
B() {
//Super();
System.out.println("class B");
}
public void finalize(){
System.out.println("Class B object destroyed");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //Parent constructor will get call
}
public void finalize(){
System.out.println("Class C object destroyed");
}
}
Je suis d’accord avec les réponses précédemment publiées, mais je souhaite ajouter une référence à l’autorité suprême sur cette question, la spécification du langage Java.
L'expression new C()
est une "expression de création d'instance de classe". Section 15.9.4 Évaluation à l'exécution des expressions de création d'instance de classe décrit les étapes d'exécution nécessaires à la création d'un objet. Notez qu'il fait référence à "l'objet" et n'alloue de l'espace qu'une seule fois, mais indique "Le constructeur sélectionné du type de classe spécifié est appelé. Il en résulte l'invocation d'au moins un constructeur pour chaque superclasse du type de classe."
Tout cela devient beaucoup plus clair en faisant la distinction entre créer un nouvel objet et appeler un constructeur. L'appel d'un constructeur ne concerne qu'une partie de la création d'objet, la partie qui exécute les initialiseurs, les constructeurs de superclasse et le corps du constructeur. Comme un C est aussi un B, le constructeur B doit s'exécuter lors de la création d'un C.
Si vous examinez la dynamique d’allocation d’objet selon la réponse this SO, il doit être clair qu’en utilisant l’opérateur new
, vous ne créez qu’un objet par déclaration. Pour clarifier davantage le doute qu'il n'y a qu'un seul objet en cours de création, parcourez ce programme:
public class A {
public static int aInstanceCount=0;
public static A aInstance;
public String aInstanceVariable;
A() {
//Super();
aInstanceCount++;
aInstanceVariable="aInstanceVar";
System.out.println("class A");
aInstance=this;
}
}
class B extends A {
public static int bInstanceCount=0;
public static B bInstance;
public String bInstanceVariable;
B() {
//Super();
bInstanceCount++;
bInstanceVariable="bInstanceVar";
System.out.println("class B");
bInstance=this;
}
}
class C extends B {
public static void main(String args[]) {
int instanceCount=0;
C c = new C(); //Parent constructor will get call
if(A.aInstance!=null){
instanceCount++;
System.out.println("Value of aInstanceVariable: "+A.aInstance.aInstanceVariable);
}
if(B.bInstance!=null){
instanceCount++;
System.out.println("Value of bInstanceVariable: "+B.bInstance.bInstanceVariable);
}
A a=A.aInstance;
B b=B.bInstance;
System.out.println("bInstanceVariable of B earlier: " + B.bInstance.bInstanceVariable);
//Now we are changing the bInstanceVariable of c which is inherited from B
c.bInstanceVariable="bInstance After modified by C";
System.out.println("bInstanceVariable of B after: " + B.bInstance.bInstanceVariable);
System.out.println("aInstanceVariable of A earlier: " + A.aInstance.aInstanceVariable);
//Now we are changing the aInstanceVariable of c which is inherited from A
c.aInstanceVariable="aInstance After modified by C";
System.out.println("bInstanceVariable of A after: " + A.aInstance.aInstanceVariable);
}
}
Le résultat:
class A
class B
Value of aInstanceVariable: aInstanceVar
Value of bInstanceVariable: bInstanceVar
bInstanceVariable of B earlier: bInstanceVar
bInstanceVariable of B after: bInstance After modified by C
aInstanceVariable of A earlier: aInstanceVar
bInstanceVariable of A after: aInstance After modified by C
Si vous pouvez le constater, le super constructeur est appelé implicitement à chaque fois si un objet de sous-classe est créé, mais étant donné que l'opérateur new
n'est utilisé qu'une seule fois, il n'y a qu'un seul objet auquel l'espace est réellement attribué. Et en modifiant l'objet aInstanceVariable
via l'objet C
c
, nous modifions en fait le aInstanceVariable
de aInstance
. Cela prouve donc clairement qu’il n’ya qu’un seul objet.
Le mot-clé super permet à une sous-classe d'appeler les méthodes et les champs de sa super-classe. Ce n'est pas une instance de l'objet superclass mais un moyen d'indiquer au compilateur les méthodes ou les champs à référencer. L'effet est le même que si la sous-classe appelle l'une de ses propres méthodes. Exemples:
Considérons un employé de la sous-classe qui étend sa superclasse Personne:
public class Employee extends Person{
public Employee()
{
//reference the superclass constructor
super();
}
public String getName()
{
//reference superclass behaviors
return super.getFirstName() + " " + super.getLastName();
}
}
Le mot clé super peut être utilisé pour référencer le constructeur de la classe Person ou l'un des comportements ou champs auxquels elle a accès (par exemple, getFirstName () et getLastName ()).
How many number of Object is created in this case.
Lorsque vous créez une instance de classe C avec C cInstance = new C();
, une seule instance (objet) de classe C est créée (aucune de A et B). Cependant, puisque C étend B et B étend A, C utilisera toutes les méthodes des classes A et B (dépend en fait des modificateurs d'accès utilisés, mais disons dans ce cas qu'ils sont publics ou par défaut).
If one object is created then how internally Super() is calling Parent class Constructor
. How Super is able to call parent class constructor.
C'est ainsi que fonctionne l'héritage. Lorsqu'un nouvel objet est créé, il appelle son constructeur de super classe et cette super classe appelle son constructeur de super classe, etc. Dans une autre fonction ordinaire, vous devez appeler explicitement super (). L'appel d'un constructeur de super classe passe donc de la mode ascendante à une exécution descendante de l'arborescence de la hiérarchie d'héritage
3 constructeurs vont appeler
Code:
class A
{
A()
{
System.out.println("In A");
}
}
class B extends A
{
B()
{
System.out.println("In B");
}
}
class C extends B
{
C()
{
System.out.println("In C");
}
}
public class InheritanceTest {
public static void main(String args[])
{
C c1=new C();
}
}
Sortie:
Dans un
En b
En C
Si vous ajoutez une ligne supplémentaire de Code System.out.println(this.hashCode())
, cela éliminera votre confusion.
Ici, dans tous les cas, hashCode()
imprimera la même hashCode
tout le temps. Cela signifie qu’il existe une seule et unique Object
unique est créée.
class A {
A() {
// super();
System.out.println(this.hashCode()); // it will print 2430287
System.out.println("class A");
}
}
class B extends A {
B() {
// super();
System.out.println(this.hashCode()); // it will print 2430287
System.out.println("class B");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //Parent constructor will get called
System.out.println(this.hashCode()); // it will print 2430287
}
}
mais il y a deux constructeurs qui sont appelés pour initialiser la variable membre Parent
. Je pense que si vous connaissez le concept de mot clé super()
qui appelle le constructeur de la classe parent
et initialise la variable membre de la classe parent
.