45 votes

Signification de l'idiome d'initialisation new Class(...){{...}}

Que signifie le bloc {{...}} dans le code suivant ?

class X {
private Y var1;

    private X() {
        Z context = new Z(new SystemThreadPool()) {{
            var1 = new Y();
        }};
    }
}

69voto

cletus Points 276888

Ça s'appelle initialisation par double accolade .

Cela signifie que vous créez une sous-classe anonyme et que le code entre les doubles crochets est essentiellement un constructeur. Il est souvent utilisé pour ajouter du contenu aux collections, car la syntaxe de Java pour créer ce qui est essentiellement des constantes de collection est quelque peu maladroite.

Donc vous pourriez le faire :

List<String> list = new ArrayList<String>() {{
  add("one");
  add("two");
  add("three");
}};

au lieu de :

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

En fait, je n'aime pas ça et je préfère faire ça :

List<String> list = Arrays.asList("one", "two", "three");

Cela n'a donc pas beaucoup de sens dans ce cas, alors que c'est le cas pour Maps, par exemple, qui n'a pas d'aide pratique.

12voto

gustafc Points 13552

Les accolades "extérieures" signifient que vous créez une sous-classe anonyme, les secondes accolades sont l'initialisateur d'objet. L'initialisateur est exécuté avant le constructeur de la classe, mais après tout super (et donc aussi après tout initialisateur de superclasse). Vous pouvez également utiliser des initialisateurs dans des classes non anonymes, ce qui est un moyen pratique d'initialiser les appels à final si vous avez plusieurs constructeurs qui ne peuvent pas s'appeler les uns les autres, ou des champs qui nécessitent une initialisation plus complexe que celle permise par les initialisateurs de champs habituels.

Considérez cette classe :

class X extends Y{
    private final int lulz;

    private static boolean someCondition(){...}
    private static boolean danger() throws SomeException { ... }
    public X(A a) throws SomeException {
        super(a); 
        lulz = someCondition()? danger() : 0;
    }
    public X(B b) throws SomeException {
        super(b); 
        lulz = someCondition()? danger() : 0;
    }
}

On pourrait le réécrire comme suit :

class X extends Y{
    private final int lulz;

    private static boolean someCondition(){...}
    private static boolean danger() throws SomeException { ... }
    { // initalizer -- might throw SomeException!
        lulz = someCondition()? danger() : 0;
    }
    public X(A a) throws SomeException { super(a); }
    public X(B b) throws SomeException { super(b); }
}

Si l'initialisateur peut lancer une exception vérifiée, tous les constructeurs doivent déclarer qu'ils peuvent la lancer.

4voto

David Santamaria Points 3181

Vous créez un classe anonyme et en utilisant le classe Instance initialiser r idiome, comme ceci :

class X {
    private Y var1;

    private X() {
        Z context = new Z(
               new SystemThreadPool()) {
                   {                        // This is the initialize idiom
                       var1 = new Y();      //
                   }                        //
               }
          );  // BTW you are missing ")"
    }
}

3voto

elpd Points 38

Comme mentionné dans les réponses précédentes, initialisation par double accolade est correct.

Il utilise une technique spécifique pour Initialisation des membres de l'instance en Java. Il s'agit d'une façon abrégée de définir, dans une définition de classe, un bloc de code partagé qui sera exécuté lorsque l'un des constructeurs de la classe sera activé.

J'ajoute le lien vers le les documentations officielles de Java en le décrivant pour avoir une vision plus large du sujet.

Desde el documentation :

Les blocs d'initialisation des variables d'instance ressemblent aux blocs d'initialisation statiques, mais sans le mot clé static. mais sans le mot-clé static :

{

// whatever code is needed for initialization goes here 

}

Le compilateur Java copie les blocs initialisateurs dans chaque constructeur. Par conséquent, cette approche peut être utilisée pour partager un bloc de code entre plusieurs constructeurs.

-4voto

Tarik Points 16118

C'est ce qu'on appelle l'initialisation de l'objet, ce qui signifie que vous attribuez une valeur à l'instance Y de l'instance Z.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X