Maison  >  Article  >  Java  >  Explication de l'appel du constructeur de classe de base Java (avec code)

Explication de l'appel du constructeur de classe de base Java (avec code)

不言
不言avant
2018-10-08 15:03:412444parcourir

Le contenu de cet article est une explication de l'appel du constructeur de classe de base Java (avec du code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Il y a un tel passage dans le chapitre 7 des classes de réutilisation dans « Pensées sur la programmation Java » qui mérite réflexion. Lorsqu'une sous-classe hérite d'une classe parent, elle implique deux classes : la classe de base et la classe dérivée (sous-classe). De l'extérieur, une classe dérivée ressemble à une nouvelle classe avec la même interface que la classe de base, avec peut-être quelques méthodes et champs supplémentaires. Mais l'héritage ne copie pas seulement l'interface de la classe de base. Lorsque vous créez un objet de classe exporté, l'objet contient un sous-objet de la classe de base. Ce sous-objet est le même que l'objet que vous créez directement avec la classe de base. La différence entre les deux est que ce dernier vient de la classe de base. à l'extérieur, tandis que le sous-objet de la classe de base. Les sous-objets sont enveloppés à l'intérieur d'objets de classe dérivés.

Cela soulève un problème très important. L'initialisation correcte du sous-objet de la classe de base est également cruciale (on peut utiliser les méthodes et les champs hérités de la classe de base dans la sous-classe), et il y a aussi une seule façon de garantir cela : appeler le constructeur de la classe de base dans le constructeur de la sous-classe pour effectuer l'initialisation.

Constructeur de classe de base sans paramètre

Nous savons que lorsque vous ne lui donnez pas de constructeur pour une classe, Java appellera automatiquement le constructeur sans paramètre pour vous, et Java l'exportera également Insérer un appel au constructeur de classe de base dans le constructeur de classe. Le code suivant illustre ce mécanisme de fonctionnement :

//: reusing/Cartoon.java
// Constructor calls during inheritance.
import static net.mindview.util.Print.*;

class Art {
  Art() { print("Art constructor"); }
}

class Drawing extends Art {
  Drawing() { print("Drawing constructor"); }
}

public class Cartoon extends Drawing {
  public Cartoon() { print("Cartoon constructor"); }
  public static void main(String[] args) {
    Cartoon x = new Cartoon();
  }
} /* Output:
Art constructor
Drawing constructor
Cartoon constructor
*///:~

Observez les résultats d'exécution du code ci-dessus. Lors de la création d'un objet Cartoon, le constructeur de sa classe parent Drawing sera d'abord appelé, et sa classe parent hérite de Classe Art, donc le constructeur de la classe Art sera appelé à nouveau, tout comme couche par couche. Bien que le constructeur de sa classe parent ne soit pas explicitement appelé dans son constructeur, Java appellera automatiquement le constructeur de sa classe parent. Même si vous ne créez pas de constructeur pour Cartoon(), le compilateur synthétisera un constructeur par défaut sans argument qui appellera le constructeur de la classe de base.

Constructeur de classe de base avec paramètres

Lorsque le constructeur de la classe de base a des paramètres, le compilateur ne l'appellera pas automatiquement et doit être appelé explicitement en utilisant le mot-clé super Constructeur de classe de base, et le transmettre les paramètres appropriés. L'exemple de code correspondant est le suivant :

//: reusing/Chess.java
// Inheritance, constructors and arguments.
import static net.mindview.util.Print.*;

class Game {
  Game(int i) {
    print("Game constructor");
  }
}

class BoardGame extends Game {
  BoardGame(int i) {
    super(i);
    print("BoardGame constructor");
  }
}   

public class Chess extends BoardGame {
  Chess() {
    super(11);
    print("Chess constructor");
  }
  public static void main(String[] args) {
    Chess x = new Chess();
  }
} /* Output:
Game constructor
BoardGame constructor
Chess constructor
*///:~

Comme le montre le code ci-dessus, vous devez utiliser super pour appeler explicitement la classe parent dans le constructeur de la sous-classe Chess et la transmettre. les paramètres appropriés. De plus, appeler le constructeur de la classe de base doit être la première chose à faire dans le constructeur de la sous-classe.

Le problème de la séquence d'appel du constructeur de classe de base

Avant cela, discutons d'abord du problème d'initialisation de la référence d'objet. En Java, les champs d'une classe peuvent être automatiquement initialisés à zéro lorsqu'il s'agit de types de base, mais les références d'objet seront initialisées à null. Nous avons souvent besoin de l'initialiser à l'emplacement approprié. Voici plusieurs emplacements où l'initialisation peut être effectuée :

1 Là où l'objet est défini. Cela signifie qu'ils peuvent toujours être initialisés avant que le constructeur ne soit appelé.

2. Dans le constructeur de la classe.

3. Juste avant l'utilisation de ces objets, cette méthode est appelée initialisation paresseuse.

En nous rappelant le point 1 ci-dessus, regardons un exemple plus complexe pour examiner la séquence d'appel du constructeur de la classe de base.

// reusing/Ex7/C7.java
// TIJ4 Chapter Reusing, Exercise 7, page 246
/* Modify Exercise 5 so that A and B have constructors with arguments instead
* of default constructors. Write a constructor for C and perform all 
* initialization within C's constructor. 
*/
 
import static org.greggordon.tools.Print.*;

class A { 
    A(char c, int i) { println("A(char, int)");} 
}

class B extends A {     
    B(String s, float f){
        super(' ', 0); 
        println("B(String, float)");
    } 
}

class C7 extends A { 
    private char c;
    private int i;
    C7(char a, int j) {     
        super(a, j); 
        c = a;
        i = j;
    }
    B b = new B("hi", 1f); // will then construct another A and then a B
    public static void main(String[] args) {
        C7 c = new C7('b', 2); // will construct an A first
    }
}

La sortie du code ci-dessus :

A(char, int)

A(char, int)

B(String, float )

Faites attention à l'ordre d'initialisation du constructeur de la classe de base, du constructeur de la sous-classe et de l'objet membre de la classe :

1. Lorsque vous créez un objet d'une classe, appelez d'abord son constructeur de classe parent (peut être sans paramètre ou paramétré, le système appellera automatiquement celui sans paramètre, et vous devez le spécifier vous-même s'il y a des paramètres). Par exemple, super(a, j)

2 en C7 ci-dessus. Exécutez ensuite son instruction d'initialisation d'objet membre et appelez le constructeur de la classe B, comme ci-dessus
B b = new B("hi", 1f), et le constructeur de B appellera d'abord le constructeur de la classe de base A.

3. Enfin, revenez au constructeur en C7 et continuez à exécuter c=a,i=j.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer