Ile obiektów powstaje w wyniku dziedziczenia w Javie?

Powiedzmy, że mam trzy klasy:

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

Kiedy tworzę instancję klasy C, wywołuje ona konstruktor super klasy. Czy powstaje więcej niż jeden obiekt? Jeśli tworzony jest tylko jeden obiekt, to w jaki sposób super() jest podobny do konstruktora innej klasy? Czy metoda super() wewnętrznie tworzy obiekt? Wiem tylko, że konstruktor jest również metodą (mogę się mylić).

moje pytania to:

  1. ile jest liczb obiektu stworzony w tym przypadku?
  2. jeśli zostanie utworzony jeden obiekt, to w jaki sposób Super() wewnętrznie wywołuje konstruktor klasy nadrzędnej?
Author: Neel, 2013-07-26

14 answers

Świetne pytanie. Sprawdzasz, jak Java inicjalizuje obiekty - i jest kilka kroków.

Wiem, że konstruktor jest również metodą (może się mylę).

Prawie w porządku. Konstruktor jest metodą specjalną. Jeśli dekompilujesz plik klasy, zobaczysz, że konstruktory zostaną przemianowane na <init>. <init> jest traktowana inaczej niż inne metody i, na przykład, nie może być wywołana jawnie, z wyjątkiem użycia słowa kluczowego new lub super. Jest to tak fundamentalne, że jest zaimplementowane w samym JVM, a nie jest czymś zdefiniowanym w języku Java.

Ile w tym przypadku zostanie wytworzonych obiektów.

Tworzony jest jeden obiekt - instancja C.

C jest dodatkowo i jednocześnie instancją B i instancją A, a także Object.

Jeśli zostanie utworzony jeden obiekt, to jak wewnętrznie super() wywołuje klasę nadrzędną Konstruktor . Jak Super jest w stanie wywołać konstruktor klasy nadrzędnej.

Tutaj wchodzimy do inicjalizacji - inicjalizacja polega na tym, jak JVM tworzy nową instancję obiektu i ustawia wszystkie wartości członkowskie-te z określonej klasy i te z superclasses. Istnieje kilka etapów zaangażowanych:

  • załaduj wszystkie odwołujące się klasy i zainicjalizuj te klasy. Inicjalizacja klasy jest sama w sobie nietrywialna, więc nie będę tego omawiał tutaj. Warto przeczytać w górę.
  • Przydziel część pamięci do przechowywania członków instancji, która obejmie wszystkich członków instancji A, B i C. Uwaga wyjaśnia to jeden aspekt Twojego pytania: w jaki sposób konstruktory klasy bazowej i jej podklas mogą aktualizować lub odnosić się do tego samego obiektu - wszystkie elementy instancji ze wszystkich klas są przechowywane jedna po drugiej w tym samym kawałku pamięci .
  • Initialize all the members to their default wartość . Na przykład, członkowie int i float będą ustawione na 0 i 0.0 f.
  • Wykonaj lub Oblicz inicjalizatory member, np:

    private int a = 10;
    private int b = a * 5;
    private String c = Singleton.getInstance().getValue();
    
  • Uwaga (1) inicjalizacja członka odbywa się ściśle w kolejności, w jakiej członkowie są zadeklarowani w klasie. Oznacza to, że odniesienia do członków później w deklaracji są łamane:

    private int a = b * 5; // Forward reference; won't compile
    private int b = 10;
    
  • Notatka (2), że w Javie jest mało używany obiekt do uruchamiania dowolnego kodu inicjalizującego wartości przed konstruktor jest wykonywany. Te bloki kodu są wykonywane w tym czasie ponownie ściśle w kolejności deklaracji:

    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;
    
  • Wykonaj konstruktor C. Konstruktory muszą albo bezpośrednio wywołać konstruktor z klasy nadrzędnej, albo kompilator automatycznie doda super() jako pierwszą linię konstruktora. Oznacza to, że konstruktory są ściśle wykonywane w kolejność:

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

Obiekt jest teraz zainicjowany i jest gotowy do użycia. Możesz zrobić kilka niebezpiecznych rzeczy, jeśli zainicjalizujesz wartość za pomocą metod instancji:

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

Tutaj a jest inicjalizowane na 0. Jest to spowodowane tym, że w momencie wywołania getB(), Java wyczyściła wartość b do wartości domyślnej (0), ale nie ustawiła jej jeszcze na 10 w drugiej fazie inicjalizacja.

W podsumowaniu-jest tylko jeden obiekt i jest tworzony i inicjowany w liczbie w etapach. Podczas tych etapów obiekt nie jest z definicji całkowicie zdefiniowany.

 52
Author: Andrew Alcock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-04 02:34:06

W kodzie zostanie utworzony tylko jeden obiekt i wywoła konstruktor klasy nadrzędnej .

Udowodnienie tworzenia obiektu:

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

To udowodni, że zostanie utworzony tylko jeden obiekt.

I o Super(). Wiem, że to nazywa konstruktor klasy rodzica . i każdy konstruktor ahve Super() jako pierwsze stwierdzenie, jak wspominasz w swoim kodzie . żebyś wiedział

Nie wiem jak to wewnętrznie nazywa super class constructor .

Hope this will make rozumiesz, że istnieje tylko instace, który tworzysz w programie

 6
Author: twister_void,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-26 09:53:49
  1. Będzie jeden i tylko jeden obiekt zostanie utworzony i ie. Obiekt.

  2. Możesz sobie wyobrazić, jak gdy Klasa A rozszerza B, wtedy wszystkie metody i zmienne są kopiowane do klasy A.

 5
Author: pankaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-26 09:37:22
  1. tylko w Twoim przypadku powstaje 1 obiekt.
  2. Kiedy konstruktor podklasy jest wywoływany, wywołuje konstruktor super klasy wewnętrznie do initailize super klasy członków.

Wywołanie konstruktora nie oznacza, że tworzysz obiekty. Obiekt jest już wytworzony podczas wywoływania konstruktora.Obiekty zostaną najpierw wytworzone przez JVM (tzn. pamięć zostanie przydzielona na stercie i wtedy zostanie wywołany konstruktor).

Konstruktor przeznaczony jest do inicjalizacji członkowie obiektów.

 2
Author: JRR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-26 09:31:46

Twoje klasy zostaną wewnętrznie przekonwertowane na coś takiego

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

Ile w tym przypadku zostanie wytworzonych obiektów.

Tylko jedna instancja C, wywołująca super() po prostu wywołuje konstruktor z klasy nadrzędnej i nie tworzy obiektu

Jeśli zostanie utworzony jeden obiekt, to jak wewnętrznie Super() wywołuje rodzica konstruktor klasy . Jak Super potrafi wywołać klasę rodzica konstruktor.

Podczas tworzenia instancji C. C'Konstruktor jest wywoływany, który najpierw wywołuje B'konstruktor, który z kolei wywołuje A'konstruktor

 2
Author: sanbhat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-26 09:36:58

Jeśli spojrzysz na dynamikę alokacji obiektów według to więc odpowiedź, musi być jasne, że używając operatora new, tworzysz tylko jeden obiekt na polecenie. Aby jeszcze bardziej wyjaśnić wątpliwości, że istnieje tylko jeden obiekt, który jest tworzony, przejdź do tego programu: {]}

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

Wyjście:

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

Jeśli zauważysz, Super konstruktor jest domyślnie wywoływany za każdym razem, gdy tworzony jest obiekt podklasy, ale ponieważ operator new jest używany tylko raz, jest tylko jeden obiekt, który jest faktycznie przydzielona przestrzeń. Modyfikując aInstanceVariable Poprzez C obiekt c, zmieniamy aInstanceVariable z aInstance. Więc to wyraźnie dowodzi, że faktycznie istnieje jeden obiekt.

 1
Author: rahulserver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:33

Kroki tworzenia obiektu podczas wywoływania konstruktora w celu utworzenia obiektu:

  1. Alokacja pamięci za pomocą init jest zakończona. Ten init wykonuje wywołanie systemowe przydzielające pamięć do tworzenia obiektów.

  2. Następnie wywoływany jest konstruktor, który inicjalizuje pola obiektu.

  3. Następnie wywołuje konstruktor super klasy (jeśli istnieje jakaś super klasa) i powtarza kroki od 1 do 3.

Co widzisz podczas dekompilacji klasy plik javap pokazuje różne wywołania do wykonania. init wywołuje wywołanie systemowe, aby zainicjować alokację pamięci, ale pole obiektu jest inicjalizowane podczas uruchamiania kodu konstruktora.

 1
Author: Ajay Bhojak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-29 07:36:49

Nie jestem pewien, jak działa polimorfizm / nadpisywanie w czasie GC.

Ale warto spróbować obejść metodę finalize we wszystkich klasach i sprawdzić, kiedy JVM kończy główną metodę.

  • jeśli tworzony jest tylko C obiekt, powinien wywołać finalize dla 'C'.
  • jeśli wszystkie A,B, C obiekt jest tworzony, powinien wywołać finalize dla A,B, C.

Myślę, że jest to najprostszy czek, który możesz zastosować.

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
Author: Learn More,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-30 14:03:38

Zgadzam się z wcześniej zamieszczonymi odpowiedziami, ale chcę dodać odniesienie do ostatecznego autorytetu w tej kwestii, specyfikacji języka Java.

Wyrażenie new C() jest "wyrażeniem tworzenia instancji klasy". Sekcja 15.9.4 Run-time Evaluation of Class Instance Creation Expressions opisuje kroki w czasie wykonania związane z tworzeniem obiektu. Zauważ, że odnosi się do "obiektu" i przydziela spację tylko raz, ale stwierdza " następnie wybrany konstruktor wywołany jest określony typ klasy. Powoduje to wywołanie co najmniej jednego konstruktora dla każdej superklasy typu klasy."

To wszystko staje się znacznie jaśniejsze, rozróżniając między tworzeniem nowego obiektu, a wywoływaniem konstruktora. Wywołanie konstruktora wykonuje tylko część tworzenia obiektu, część, która uruchamia inicjatory, konstruktory klasy nadrzędnej i ciało konstruktora. Ponieważ C jest również B, konstruktor B musi działać podczas tworzenia C.

 1
Author: Patricia Shanahan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-31 04:21:27

Słowo kluczowe super umożliwia podklasie wywoływanie metod i pól swojej superklasy. Nie jest to instancja obiektu superclass , ale sposób na wskazanie kompilatorowi, do których metod lub pól należy się odwoływać. Efekt jest taki sam, jakby podklasa wywołała jedną ze swoich własnych metod. Przykłady:

Rozważ pracownika podklasy, który rozszerza swoją osobę nadklasyczną:

public class Employee extends Person{

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

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

Słowo kluczowe super może być użyte do odniesienia się do konstruktora klasy Person lub dowolnego z zachowania lub pola, do których ma dostęp (np. getFirstName () i getLastName ()).

 1
Author: Backtrack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-01 06:21:14
  1. W Twoim przypadku powstaje jeden obiekt

  2. Podczas wykonywania następujących czynności, ta super () będzie dostarczana przez kompilator w domyśle

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

Jest to podobne do wywołania super() wewnątrz twoich metod

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

Słowo kluczowe super może być również użyte, gdy metoda jest nadpisana w bieżącej klasie, ale chcesz wywołać metodę super class.

Super() will sprawia, że wszystkie konstruktory odnoszą się do jednej klasy. (Dla łatwego zrozumienia: Its like all funkcje Członkowskie należą do tej samej klasy.) Będzie wywoływać tylko wszystkie metody konstruktora.

Więc wykonała tylko pracę wywołania konstruktora, więc super() nie stworzy żadnego obiektu. To tylko odwoływanie się do funkcji członka.

 1
Author: Pandiyan Cool,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-01 09:50:40
How many number of Object is created in this case.

Gdy tworzysz instancję klasy C przez C cInstance = new C(); tworzy się pojedynczą instancję (obiekt) klasy C (Brak A i B). Ponieważ jednak C rozszerza B i B rozszerza A, C będzie miał wszystkie metody klasy A i B (W rzeczywistości zależy od użytych modyfikatorów dostępu, ale powiedzmy, że w tym przypadku są publiczne lub domyślne).

If one object is created then how internally Super() is calling Parent class Constructor
. How Super is able to call parent class constructor.
Tak działa dziedziczenie. Kiedy nowy obiekt zostanie utworzony, będzie nazywał go super class constructor, a ta super class nazwie go super class constructor i i tak dalej. W innych zwykłych funkcjach musisz jawnie wywołać super (). Tak więc wywołanie konstruktora super klasy przechodzi w modę oddolną, podczas gdy wykonanie idzie w modę odgórną drzewa hierarchii dziedziczenia
 1
Author: Aniket Thakur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-02 04:59:56

Jeśli dodasz jeszcze jeden wiersz kodu System.out.println(this.hashCode()) usunie Twoje zamieszanie.

Tutaj w każdym przypadku hashCode() będzie drukować to samo hashCode cały czas. Oznacza to, że istnieje jeden i tylko jeden unikalny Object jest tworzony.

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

Ale są dwa konstruktory, które są wywoływane do inicjalizacji zmiennej członkowskiej Parent. Myślę, że jeśli znasz pojęcie słowa kluczowego super(), które wywołuje konstruktor klasy parent i inicjalizuje zmienną składową klasy parent.

 0
Author: Vikrant Kashyap,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-09 06:44:23

3 konstruktory wywołają

Kod:

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

}

Wyjście:

W

W B

W C

 0
Author: Usman Yaqoob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-29 12:20:05