webentwicklung-frage-antwort-db.com.de

Wie viele Objekte werden aufgrund der Vererbung in Java erstellt?

Nehmen wir an, ich habe drei Klassen:

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
    }
}

Wenn ich eine Instanz der Klasse C erstelle, ruft sie den Konstruktor der Superklasse auf. Gibt es also mehr als ein Objekt, das erstellt wird? Wenn nur ein Objekt erstellt wird, wie ist dann super () der Konstruktor einer anderen Klasse? Erstellt die super () - Methode intern ein Objekt? Was ich weiß ist, der Konstruktor ist auch eine Methode (ich kann mich irren).

Meine Fragen sind:

  1. Wie viele Objekte werden in diesem Fall erstellt?
  2. Wenn ein Objekt erstellt wird, wie ruft Super () dann den übergeordneten Klassenkonstruktor intern auf?
50
Java_begins

Gute Frage. Was Sie prüfen, ist, wie Java Objekte initialisiert - und es gibt eine Reihe von Schritten.

ich weiß, dass Konstruktor auch eine Methode ist (vielleicht irre ich mich).

Fast richtig Der Konstruktor ist eine spezielle Methode. Wenn Sie eine Klassendatei dekompilieren, werden die Konstruktoren in <init> umbenannt. <init> wird anders behandelt als andere Methoden und kann beispielsweise nur mit dem Schlüsselwort new oder super explizit aufgerufen werden. Dies ist so grundlegend, dass es in der JVM selbst implementiert ist und nicht in der Sprache Java definiert ist.

Wie viele Anzahl von Objekten wird in diesem Fall erstellt.

Ein Objekt wird erstellt - eine Instanz von C.

C ist zusätzlich und gleichzeitig eine Instanz von B und eine Instanz von A und auch Object.

Wenn ein Objekt erstellt wird, ruft super() intern den Konstruktor der übergeordneten Klasse auf. Wie Super den übergeordneten Klassenkonstruktor aufrufen kann.

Hier kommen wir zur Initialisierung. Bei der Initialisierung erstellt die JVM eine neue Instanz eines Objekts und legt alle Elementwerte fest - die der spezifischen Klasse und die der Superklassen. Es gibt verschiedene Phasen:

  • Laden Sie alle referenzierten Klassen und initialisieren Sie diese Klassen. Die Klasseninitialisierung selbst ist nicht trivial, daher werde ich hier nicht darauf eingehen. Es lohnt sich zu lesen.
  • Weisen Sie einen Teil des Arbeitsspeichers für die Mitglieder der Instanz zu, der alle Mitglieder von A, B und C enthält. NOTE Dies erklärt einen Aspekt Ihrer Frage: Wie können die Konstruktoren der Basisklasse und ihrer Unterklassen dasselbe Objekt aktualisieren oder auf dasselbe verweisen - alle Mitglieder von Die Instanzen aller Klassen werden nacheinander im selben Speicherblock abgelegt .
  • Initialisieren Sie alle Mitglieder auf ihren Standardwert . Beispielsweise werden die Member int und float auf 0 und 0.0f gesetzt.
  • Ausführen oder Berechnen der Elementinitialisierer, z. B .:

    private int a = 10;
    private int b = a * 5;
    private String c = Singleton.getInstance().getValue();
    
  • Beachten Sie (1), dass die Member-Initialisierung ausschließlich in der Reihenfolge erfolgt, in der die Member in der Klasse deklariert sind. Dies bedeutet, dass Verweise auf Mitglieder zu einem späteren Zeitpunkt in der Erklärung ungültig sind:

    private int a = b * 5; // Forward reference; won't compile
    private int b = 10;
    
  • Beachten Sie (2), dass es in Java eine nicht ausreichend genutzte Funktion gibt, um beliebigen Code zum Initialisieren von Werten auszuführen, bevor der Konstruktor ausgeführt wird . Diese Codeblöcke werden zu diesem Zeitpunkt wieder streng in der Reihenfolge der Deklaration ausgeführt:

    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;
    
  • Führen Sie den Konstruktor von C aus. Konstruktoren müssen entweder direkt einen Konstruktor aus der Superklasse aufrufen, oder der Compiler fügt automatisch super() als erste Zeile des Konstruktors hinzu. Dies bedeutet, dass die Konstruktoren strikt in der folgenden Reihenfolge ausgeführt werden:

    1. Object
    2. A
    3. B
    4. C

Das Objekt ist jetzt initialisiert und kann verwendet werden. Sie können gefährliche Dinge tun, wenn Sie den Wert mithilfe von Instanzmethoden initialisieren:

public class Wrong {
    int a = getB(); // Don't do this!
    int b = 10;
    public int getB() {
         return b;
    }
}

Hier wird a auf 0 initialisiert. Dies liegt daran, dass getB() zum Zeitpunkt des Aufrufs Java den Wert von b auf den Standardwert (0) zurückgesetzt hat, ihn jedoch noch nicht festgelegt hat 10 in der zweiten Phase der Initialisierung.

Zusammenfassend lässt sich sagen, dass es nur ein Objekt gibt, das in mehreren Schritten erstellt und initialisiert wird. Während dieser Phasen ist das Objekt per Definition nicht vollständig definiert.

56
Andrew Alcock

Im Code wird nur ein Objekt erstellt und der übergeordnete Klassenkonstruktor super aufgerufen. 

Nachweis der Objekterstellung: 

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();
    }
}

Dies wird beweisen, dass nur ein Objekt erstellt wird. 

Und über Super(). Was ich weiß, nennt es Konstruktor der übergeordneten Klasse. und jeder Konstruktor hat Super() als erste Anweisung, wie Sie sie in Ihrem Code erwähnen. so dass Sie wissen

Ich weiß nicht, wie der Superklassekonstruktor intern aufgerufen wird. 

Ich hoffe, Sie werden dadurch verstehen, dass es nur das Programm gibt, das Sie im Programm erstellen

6
twister_void
  1. Es wird ein und nur ein Objekt erstellt. Ein Objekt.

  2. Sie können sich vorstellen, als wenn Klasse A B erweitert, dann werden alle Methoden und Variablen in Klasse A kopiert.

5
pankaj
  1. In Ihrem Fall werden nur 1 Objekte erstellt.
  2. Wenn der Konstruktor der Unterklassen aufgerufen wird, ruft er intern den Konstruktor der Oberklasse auf, um die Mitglieder der Oberklasse zu initialisieren.

Das Aufrufen des Konstruktors bedeutet nicht, dass Sie Objekte erstellen. Beim Aufrufen des Konstruktors wird bereits ein Objekt erstellt. Die Objekte werden zuerst von der JVM erstellt (d. H. Der Speicher wird auf dem Heap reserviert und anschließend der Konstruktor aufgerufen).

Konstruktor ist zum Initialisieren der Member von Objekten gedacht.

2
JRR

Ihre Klassen werden intern in so etwas umgewandelt

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 
    }
}

Wie viele Objekte werden in diesem Fall erstellt?.

Nur eine Instanz, die eine Instanz von C ist, ruft super() auf, nur ruft den -Konstruktor der parent-Klasse auf und erstellt kein Objekt

Wenn ein Objekt erstellt wird, dann ruft Super () intern Parent .__ auf. Klasse Konstruktor. Wie kann Super die übergeordnete Klasse aufrufen Konstrukteur.

Wenn Sie die Instanz von C erstellen. Der Konstruktor von C wird aufgerufen, der zuerst den Konstruktor von B aufruft, der wiederum den Konstruktor von A aufruft

2
sanbhat
  1. In Ihrem Fall wird ein Objekt erstellt

  2. in den folgenden Fällen wird dieses Super () implizit vom Compiler bereitgestellt

    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(); //
    }
    }
    

Es ist vergleichbar mit dem Aufruf eines Super () in Ihren Methoden

    B() {
        super();
        System.out.println("class B");
    }

Das Schlüsselwort super kann auch verwendet werden, wenn eine Methode in der aktuellen Klasse überschrieben wird, Sie jedoch die Superklassenmethode aufrufen möchten.

super () will alle Konstruktoren auf eine Klasse verweisen. (Zum besseren Verständnis: Alle Mitgliedsfunktionen gehören zu derselben Klasse.) Es werden nur alle Konstruktormethoden aufgerufen.

Es ist also die Aufgabe, nur Konstruktor aufzurufen, so dass super () keine Objekterstellung vornimmt. Es bezieht sich nur auf die Mitgliederfunktionen.

1
Pandiyan Cool

Schritte der Objekterstellung beim Aufruf eines Konstruktors zum Erstellen eines Objekts:

  1. Die Speicherzuordnung mit init ist abgeschlossen. Dieser init führt einen Systemaufruf aus, um Speicher zuzuweisen für die Objekterstellung.

  2. Dann wird Ihr Konstruktor aufgerufen, um die Felder des Objekts zu initialisieren.

  3. Dann ruft es Superklassenkonstruktor (wenn es eine Superklasse gibt) und Wiederholungen von Schritt 1 bis 3 auf.

Was Sie sehen, wenn Sie eine Klassendatei mit javap dekompilieren, zeigt verschiedene Aufrufe an. init führt einen Systemaufruf aus, um die Speicherzuordnung zu initialisieren, das Objektfeld wird jedoch initialisiert, wenn der Konstruktorcode ausgeführt wird.

1
Ajay Bhojak

Ich bin mir nicht sicher, wie Polymorphismus/Overriding zum Zeitpunkt der GC funktioniert. 

Es sollte jedoch einen Versuch wert sein, die finalize-Methode in allen Klassen zu überschreiben und zu überprüfen, wann die Hauptmethode von JVM beendet wird. 

  • Wenn nur ein C-Objekt erstellt wird, sollte finalize für 'C' aufgerufen werden.
  • Wenn alle A, B, C Objekte erstellt werden, sollte finalize für A, B, C aufgerufen werden.

Ich denke, das ist die einfachste Prüfung, die Sie anwenden können. 

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");
    } 
}
1
Learn More

Ich stimme mit den zuvor veröffentlichten Antworten überein, möchte jedoch die letzte Autorität zu diesem Thema, die Java-Sprachspezifikation, hinzufügen.

Der Ausdruck new C() ist ein Ausdruck zur Erzeugung von Klasseninstanzen. Abschnitt 15.9.4 Laufzeitauswertung von Ausdrücken für die Erstellung von Klasseninstanzen beschreibt die zum Erstellen eines Objekts erforderlichen Laufzeitschritte. Beachten Sie, dass es sich auf "das Objekt" bezieht und nur einmal Speicherplatz zuordnet, aber "Als nächstes wird der ausgewählte Konstruktor des angegebenen Klassentyps aufgerufen. Dies führt dazu, dass für jede Oberklasse des Klassentyps mindestens ein Konstruktor aufgerufen wird."

Dies alles wird viel klarer, wenn zwischen dem Erstellen eines neuen Objekts und dem Aufruf eines Konstruktors unterschieden wird. Das Aufrufen eines Konstruktors führt nur einen Teil der Objekterstellung, den Teil aus, der Initialisierer, Superklassekonstruktoren und den Rumpf des Konstruktors ausführt. Da ein C auch ein B ist, muss der B-Konstruktor während der Erstellung eines C ausgeführt werden.

1

Wenn Sie die Dynamik der Objektzuordnung anhand der Antwort " this SO" betrachten, muss klar sein, dass Sie mit dem Operator new nur ein Objekt pro Anweisung erstellen. Um den Zweifel weiter zu verdeutlichen, dass nur ein Objekt erstellt wird, gehen Sie durch dieses Programm:

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);
    }
}

Die Ausgabe:

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

Wenn Sie feststellen, wird der Superkonstruktor jedes Mal implizit aufgerufen, wenn ein Unterklassenobjekt erstellt wird. Da der Operator new jedoch nur einmal verwendet wird, gibt es nur ein Objekt, dem tatsächlich der Speicherplatz zugewiesen wird. Und durch die Änderung der aInstanceVariable über das C-Objekt c ändern wir tatsächlich die aInstanceVariable der aInstance. Es zeigt also eindeutig, dass es tatsächlich einen Gegenstand gibt.

1
rahulserver

Das Schlüsselwort super ermöglicht einer Unterklasse den Aufruf der Methoden und Felder ihrer Oberklasse. Es ist keine Instanz des übergeordneten Objekts, sondern eine Möglichkeit, dem Compiler mitzuteilen, auf welche Methoden oder Felder er verweisen soll. Der Effekt ist derselbe, als wenn die Unterklasse eine ihrer eigenen Methoden aufruft. Beispiele:

Betrachten Sie eine Unterklasse Employee, die ihre Superklasse Person erweitert:

public class Employee extends Person{

   public Employee()
   {
     //reference the superclass constructor 
     super(); 
   }

   public String getName()
   {
     //reference superclass behaviors
     return super.getFirstName() + " " + super.getLastName();
   }
 } 

Das Super-Schlüsselwort kann verwendet werden, um auf den Konstruktor der Person-Klasse oder ein beliebiges Verhalten oder Feld zu verweisen, auf das es Zugriff hat (z. B. getFirstName () und getLastName ()). 

1
Backtrack
How many number of Object is created in this case.

Wenn Sie eine Instanz der Klasse C mit C cInstance = new C(); erstellen, wird eine einzelne Instanz (Objekt) der Klasse C erstellt (Keine von A und B). Da sich C jedoch um B und B um A erstreckt, verfügt C über alle Methoden der Klassen A und B (Tatsächlich hängt es von den verwendeten Zugriffsmodifizierern ab, sagen wir für diesen Fall, dass sie öffentlich oder standardmäßig sind).

If one object is created then how internally Super() is calling Parent class Constructor
. How Super is able to call parent class constructor.

So funktioniert Vererbung. Wenn ein neues Objekt erstellt wird, ruft es seinen Superklassenkonstruktor auf, und diese Superklasse nennt ihren Superklassenkonstruktor und so weiter. In einer anderen gewöhnlichen Funktion müssen Sie super () explizit aufrufen. Der Aufruf des Superklassenkonstruktors erfolgt also von unten nach oben, während die Ausführung von oben nach unten in der Vererbungshierarchiestruktur erfolgt

1
Aniket Thakur

3 Konstruktoren rufen an

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();
    }

}

Ausgabe:

In einem

In B

In c

0
Usman Yaqoob

Wenn Sie eine weitere Codezeile hinzufügen, wird System.out.println(this.hashCode()) Ihre Verwirrung beseitigen.

In diesem Fall wird hashCode() immer die gleiche hashCode ausgegeben. Dies bedeutet, dass es nur eine einzige Object gibt, die erstellt wurde.

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
    }
}

es gibt jedoch zwei Konstruktoren, die aufgerufen werden, um die Membervariable Parent zu initialisieren. Ich denke, wenn Sie das Konzept des super()-Schlüsselworts kennen, das den Konstruktor der parent-Klasse aufruft, und die Member-Variable der parent-Klasse initialisieren.

0
Vikrant Kashyap