web-dev-qa-db-fra.com

Qu'est-ce qu'un bloc d'initialisation?

On peut mettre du code dans un constructeur, une méthode ou un bloc d’initialisation. Quelle est l'utilisation du bloc d'initialisation? Est-il nécessaire que tous les programmes Java doivent l'avoir? 

83
Sumithra

Tout d’abord, il existe deux types de blocs d’initialisation :

  • blocs d'initialisation d'instance, et
  • blocs d'initialisation statiques.

Ce code devrait illustrer leur utilisation et dans quel ordre ils sont exécutés:

public class Test {

    static int staticVariable;
    int nonStaticVariable;        

    // Static initialization block:
    // Runs once (when the class is initialized)
    static {
        System.out.println("Static initalization.");
        staticVariable = 5;
    }

    // Instance initialization block:
    // Runs each time you instantiate an object
    {
        System.out.println("Instance initialization.");
        nonStaticVariable = 7;
    }

    public Test() {
        System.out.println("Constructor.");
    }

    public static void main(String[] args) {
        new Test();
        new Test();
    }
}

Impressions:

Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.

Les blocs de personnalisation d'instance sont utiles si vous souhaitez qu'un code soit exécuté quel que soit le constructeur utilisé ou si vous souhaitez effectuer une initialisation d'instance pour les classes anonymes.

157
aioobe

aimerait ajouter à la réponse de @ aioobe

Ordre d'exécution:

  1. blocs d'initialisation statiques de super classes

  2. blocs d'initialisation statiques de la classe

  3. blocs d'initialisation d'instance de super classes

  4. constructeurs de super classes

  5. blocs d'initialisation d'instance de la classe

  6. constructeur de la classe.

Quelques points supplémentaires à garder à l'esprit (le point 1 est la réitération de la réponse de @ aioobe):

  1. Le code du bloc d'initialisation statique sera exécuté au moment du chargement de la classe (et oui, cela signifie qu'une seule fois par chargement de la classe), avant la construction des instances de la classe et avant l'appel des méthodes statiques.

  2. Le bloc d'initialisation d'instance est en fait copié par le compilateur Java dans chaque constructeur de la classe. Ainsi, chaque fois que le code du bloc d’initialisation d’instance est exécuté exactement avant le code du constructeur.

87
Biman Tripathy

Bonne réponse de aioobe Ajoutant quelques points de plus

public class StaticTest extends parent {
    static {
        System.out.println("inside satic block");
    }

    StaticTest() {
        System.out.println("inside constructor of child");
    }

    {
        System.out.println("inside initialization block");
    }

    public static void main(String[] args) {
        new StaticTest();
        new StaticTest();
        System.out.println("inside main");
    }
}

class parent {
    static {
        System.out.println("inside parent Static block");
    }
    {
        System.out.println("inside parent initialisation block");
    }

    parent() {
        System.out.println("inside parent constructor");
    }
}

cela donne 

inside parent Static block
inside satic block
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside parent initialisation block
inside parent constructor
inside initialization block
inside constructor of child
inside main

c'est comme dire l'évidence mais semble un peu plus clair.

6
Gaurav

L'exemple de code, qui est approuvé comme réponse ici, est correct, mais je ne le suis pas. Cela ne montre pas ce qui se passe et je vais vous montrer un bon exemple pour comprendre le fonctionnement de la machine virtuelle Java:

package test;

    class A {
        A() {
            print();
        }

        void print() {
            System.out.println("A");
        }
    }

    class B extends A {
        static int staticVariable2 = 123456;
        static int staticVariable;

        static
        {
            System.out.println(staticVariable2);
            System.out.println("Static Initialization block");
            staticVariable = Math.round(3.5f);
        }

        int instanceVariable;

        {
            System.out.println("Initialization block");
            instanceVariable = Math.round(3.5f);
            staticVariable = Math.round(3.5f);
        }

        B() {
            System.out.println("Constructor");
        }

        public static void main(String[] args) {
            A a = new B();
            a.print();
            System.out.println("main");
        }

        void print() {
            System.out.println(instanceVariable);
        }

        static void somethingElse() {
            System.out.println("Static method");
        }
    }

Avant de commencer à commenter le code source, je vais vous donner une brève explication des variables statiques d'une classe:

La première chose à faire est qu’elles sont appelées variables de classe, elles appartiennent à la classe et non à une instance particulière de la classe. Toutes les instances de la classe partagent cette variable statique (classe). Chaque variable a une valeur par défaut, en fonction du type de primitive ou de référence. Une autre chose est que lorsque vous réaffectez la variable statique dans certains membres de la classe (blocs d'initialisation, constructeurs, méthodes, propriétés) et que vous modifiez ainsi la valeur de la variable statique, pas pour une instance particulière, vous la modifiez pour tous. les instances. Pour conclure la partie statique, je dirai que les variables statiques d’une classe ne sont pas créées lors de la première instanciation de la classe; elles sont créées lors de la définition de votre classe. Elles existent dans la JVM sans qu’aucune instance ne soit nécessaire. Par conséquent, l'accès correct des membres statiques à partir d'une classe externe (classe dans laquelle ils ne sont pas définis) consiste à utiliser le nom de la classe suivant le point, puis le membre statique auquel vous souhaitez accéder (modèle: <CLASS_NAME>.<STATIC_VARIABLE_NAME>).

Regardons maintenant le code ci-dessus:

Le point d’entrée est la méthode principale - il n’ya que trois lignes de code. Je veux me référer à l'exemple qui est actuellement approuvé. Selon lui, la première chose qui doit être imprimée après l’impression "Bloc d’initialisation statique" est "Bloc d’initialisation" et voici mon désaccord, le bloc d’initialisation non statique n’est pas appelé avant le constructeur, il est appelé avant toute initialisation des constructeurs. de la classe dans laquelle le bloc d’initialisation est défini. Le constructeur de la classe est le premier élément impliqué lorsque vous créez un objet (instance de la classe), puis lorsque vous entrez le constructeur, la première partie appelée est soit un super constructeur implicite (par défaut), soit un super constructeur explicite, soit un appel explicite à un autre utilisateur surchargé. constructeur (mais à un moment donné s'il existe une chaîne de constructeurs surchargés, le dernier appelle un super constructeur, de manière implicite ou explicite). 

Il existe une création polymorphe d'un objet, mais avant d'entrer dans la classe B et sa méthode principale, la machine virtuelle Java initialise toutes les variables de classe (statiques), puis passe par les blocs d'initialisation statiques, le cas échéant, puis entre dans la classe B et commence par le début. exécution de la méthode principale. Il va au constructeur de la classe B puis appelle immédiatement (implicitement) le constructeur de la classe A, en utilisant le polymorphisme la méthode (méthode surchargée) appelée dans le corps du constructeur de la classe A est celle qui est définie en classe B et dans ce cas la variable nommée instanceVariable est utilisée avant la réinitialisation. Après la fermeture du constructeur de la classe B, le fil est renvoyé au constructeur de la classe B, mais il passe d'abord au bloc d'initialisation non statique avant l'impression de "Constructeur". Pour une meilleure compréhension, corrigez-le avec un IDE, je préfère Eclipse.

3
nenito

Le bloc d'initialisation contient le code qui est toujours exécuté chaque fois qu'une instance est créée. Il est utilisé pour déclarer/initialiser la partie commune de différents constructeurs d'une classe. 

L’ordre des constructeurs d’initialisation et du bloc d’initialisation n’importe pas, le bloc d’initialisation est toujours exécuté avant le constructeur. 

Et si nous voulons exécuter du code une fois pour tous les objets d'une classe?

Nous utilisons Static Block en Java. 

1
roottraveller

Les blocs d'initialisation sont exécutés à chaque initialisation de la classe et avant l'appel des constructeurs. Ils sont généralement placés au-dessus des constructeurs entre accolades. Il n'est pas du tout nécessaire de les inclure dans vos cours.

Ils sont généralement utilisés pour initialiser les variables de référence. Cette page donne une bonne explication

0
Gaurav Saxena

Initialisme Affiche le texte à l'intérieur de l'élément <abbr> dans une taille de police légèrement inférieure.

0

La question n'est pas tout à fait claire, mais voici une brève description de la manière dont vous pouvez initialiser les données dans un objet. Supposons que vous ayez une classe A qui contient une liste d'objets.

1) Mettez les valeurs initiales dans la déclaration de champ:

class A {
    private List<Object> data = new ArrayList<Object>();
}

2) Attribuer des valeurs initiales dans le constructeur:

class A {
    private List<Object> data;
    public A() {
        data = new ArrayList<Object>();
    }
}

Ces deux supposent que vous ne voulez pas passer "data" en tant qu'argument constructeur.

Les choses deviennent un peu délicates si vous mélangez des constructeurs surchargés avec des données internes comme ci-dessus. Considérer:

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        data = new ArrayList<Object>();
        name = "Default name";
        userFriendlyName = "Default user friendly name";
    }

    public B(String name) {
        data = new ArrayList<Object>();
        this.name = name;
        userFriendlyName = name;
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

Notez qu'il y a beaucoup de code répété. Vous pouvez résoudre ce problème en faisant en sorte que les constructeurs s’appellent, ou vous pouvez avoir une méthode d’initialisation privée que chaque constructeur appelle:

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        this("Default name", "Default user friendly name");
    }

    public B(String name) {
        this(name, name);
    }

    public B(String name, String userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

ou

class B {
    private List<Object> data;
    private String name;
    private String userFriendlyName;

    public B() {
        init("Default name", "Default user friendly name");
    }

    public B(String name) {
        init(name, name);
    }

    public B(String name, String userFriendlyName) {
        init(name, userFriendlyName);
    }

    private void init(String _name, String _userFriendlyName) {
        data = new ArrayList<Object>();
        this.name = name;
        this.userFriendlyName = userFriendlyName;
    }
}

Les deux sont (plus ou moins) équivalents.

J'espère que cela vous indique comment initialiser les données dans vos objets. Je ne parlerai pas de blocs d'initialisation statiques car c'est probablement un peu avancé pour le moment.

EDIT: J'ai interprété votre question comme suit: "Comment initialiser mes variables d'instance" et non pas "Comment fonctionnent les blocs d'initialisation", car les blocs d'initialisation sont un concept relativement avancé le concept plus simple. Je peux me tromper.

0
Cameron Skinner
public class StaticInitializationBlock {

    static int staticVariable;
    int instanceVariable;

    // Static Initialization Block
    static { 
        System.out.println("Static block");
        staticVariable = 5;

    }

    // Instance Initialization Block
    { 

        instanceVariable = 7;
        System.out.println("Instance Block");
        System.out.println(staticVariable);
        System.out.println(instanceVariable);

        staticVariable = 10;
    }


    public StaticInitializationBlock() { 

        System.out.println("Constructor");
    }

    public static void main(String[] args) {
        new StaticInitializationBlock();
        new StaticInitializationBlock();
    }

}

Sortie:

Static block
Instance Block
5
7
Constructor
Instance Block
10
7
Constructor
0